xref: /netbsd-src/sys/dev/ieee1394/fwohci.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
1 /*	$NetBSD: fwohci.c,v 1.41 2001/07/18 02:59:54 onoe Exp $	*/
2 
3 #define DOUBLEBUF 1
4 #define NO_THREAD 1
5 /*-
6  * Copyright (c) 2000 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Matt Thomas of 3am Software Foundry.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *        This product includes software developed by the NetBSD
23  *        Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 /*
42  * IEEE1394 Open Host Controller Interface
43  *	based on OHCI Specification 1.1 (January 6, 2000)
44  * The first version to support network interface part is wrtten by
45  * Atsushi Onoe <onoe@netbsd.org>.
46  */
47 
48 /*
49  * The first version to support isochronous acquisition part is wrtten
50  * by HAYAKAWA Koichi <haya@netbsd.org>.
51  */
52 
53 #include "opt_inet.h"
54 
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/kthread.h>
58 #include <sys/types.h>
59 #include <sys/socket.h>
60 #include <sys/callout.h>
61 #include <sys/device.h>
62 #include <sys/kernel.h>
63 #include <sys/malloc.h>
64 #include <sys/mbuf.h>
65 
66 #if __NetBSD_Version__ >= 105010000
67 #include <uvm/uvm_extern.h>
68 #else
69 #include <vm/vm.h>
70 #endif
71 
72 #include <machine/bus.h>
73 #include <machine/intr.h>
74 
75 #include <dev/ieee1394/ieee1394reg.h>
76 #include <dev/ieee1394/fwohcireg.h>
77 
78 #include <dev/ieee1394/ieee1394var.h>
79 #include <dev/ieee1394/fwohcivar.h>
80 
81 static const char * const ieee1394_speeds[] = { IEEE1394_SPD_STRINGS };
82 
83 #if 0
84 static int fwohci_dnamem_alloc(struct fwohci_softc *sc, int size,
85     int alignment, bus_dmamap_t *mapp, caddr_t *kvap, int flags);
86 #endif
87 static void fwohci_create_event_thread(void *);
88 static void fwohci_thread_init(void *);
89 
90 static void fwohci_event_thread(struct fwohci_softc *);
91 static void fwohci_hw_init(struct fwohci_softc *);
92 static void fwohci_power(int, void *);
93 static void fwohci_shutdown(void *);
94 
95 static int  fwohci_desc_alloc(struct fwohci_softc *);
96 static struct fwohci_desc *fwohci_desc_get(struct fwohci_softc *, int);
97 static void fwohci_desc_put(struct fwohci_softc *, struct fwohci_desc *, int);
98 
99 static int  fwohci_ctx_alloc(struct fwohci_softc *, struct fwohci_ctx **,
100     int, int, int);
101 static void fwohci_ctx_free(struct fwohci_softc *, struct fwohci_ctx *);
102 static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *);
103 
104 static int  fwohci_buf_alloc(struct fwohci_softc *, struct fwohci_buf *);
105 static void fwohci_buf_free(struct fwohci_softc *, struct fwohci_buf *);
106 static void fwohci_buf_init_rx(struct fwohci_softc *);
107 static void fwohci_buf_start_rx(struct fwohci_softc *);
108 static void fwohci_buf_stop_tx(struct fwohci_softc *);
109 static void fwohci_buf_stop_rx(struct fwohci_softc *);
110 static void fwohci_buf_next(struct fwohci_softc *, struct fwohci_ctx *);
111 static int  fwohci_buf_pktget(struct fwohci_softc *, struct fwohci_buf **,
112     caddr_t *, int);
113 static int  fwohci_buf_input(struct fwohci_softc *, struct fwohci_ctx *,
114     struct fwohci_pkt *);
115 static int  fwohci_buf_input_ppb(struct fwohci_softc *, struct fwohci_ctx *,
116     struct fwohci_pkt *);
117 
118 static u_int8_t fwohci_phy_read(struct fwohci_softc *, u_int8_t);
119 static void fwohci_phy_write(struct fwohci_softc *, u_int8_t, u_int8_t);
120 static void fwohci_phy_busreset(struct fwohci_softc *);
121 static void fwohci_phy_input(struct fwohci_softc *, struct fwohci_pkt *);
122 
123 static int  fwohci_handler_set(struct fwohci_softc *, int, u_int32_t, u_int32_t,
124     int (*)(struct fwohci_softc *, void *, struct fwohci_pkt *), void *);
125 
126 static void fwohci_arrq_input(struct fwohci_softc *, struct fwohci_ctx *);
127 static void fwohci_arrs_input(struct fwohci_softc *, struct fwohci_ctx *);
128 static void fwohci_ir_input(struct fwohci_softc *, struct fwohci_ctx *);
129 
130 static int  fwohci_at_output(struct fwohci_softc *, struct fwohci_ctx *,
131     struct fwohci_pkt *);
132 static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *, int);
133 static void fwohci_atrs_output(struct fwohci_softc *, int, struct fwohci_pkt *,
134     struct fwohci_pkt *);
135 
136 static int  fwohci_guidrom_init(struct fwohci_softc *);
137 static void fwohci_configrom_init(struct fwohci_softc *);
138 static int  fwohci_configrom_input(struct fwohci_softc *, void *,
139     struct fwohci_pkt *);
140 static void fwohci_selfid_init(struct fwohci_softc *);
141 static int  fwohci_selfid_input(struct fwohci_softc *);
142 
143 static void fwohci_csr_init(struct fwohci_softc *);
144 static int  fwohci_csr_input(struct fwohci_softc *, void *,
145     struct fwohci_pkt *);
146 
147 static void fwohci_uid_collect(struct fwohci_softc *);
148 static void fwohci_uid_req(struct fwohci_softc *, int);
149 static int  fwohci_uid_input(struct fwohci_softc *, void *,
150     struct fwohci_pkt *);
151 static int  fwohci_uid_lookup(struct fwohci_softc *, const u_int8_t *);
152 static void fwohci_check_nodes(struct fwohci_softc *);
153 
154 static int  fwohci_if_inreg(struct device *, u_int32_t, u_int32_t,
155     void (*)(struct device *, struct mbuf *));
156 static int  fwohci_if_input(struct fwohci_softc *, void *, struct fwohci_pkt *);
157 static int  fwohci_if_input_iso(struct fwohci_softc *, void *, struct fwohci_pkt *);
158 static int  fwohci_if_output(struct device *, struct mbuf *,
159     void (*)(struct device *, struct mbuf *));
160 static int fwohci_if_setiso(struct device *, u_int32_t, u_int32_t, u_int32_t,
161     void (*)(struct device *, struct mbuf *));
162 static int  fwohci_read(struct ieee1394_abuf *);
163 static int  fwohci_write(struct ieee1394_abuf *);
164 static int  fwohci_read_resp(struct fwohci_softc *, void *, struct fwohci_pkt *);
165 static int  fwohci_write_ack(struct fwohci_softc *, void *, struct fwohci_pkt *);
166 static int  fwohci_read_multi_resp(struct fwohci_softc *, void *,
167     struct fwohci_pkt *);
168 static int  fwohci_inreg(struct ieee1394_abuf *, int);
169 static int  fwohci_parse_input(struct fwohci_softc *, void *,
170     struct fwohci_pkt *);
171 static int  fwohci_submatch(struct device *, struct cfdata *, void *);
172 
173 #ifdef FW_DEBUG
174 static void fwohci_show_intr(struct fwohci_softc *, u_int32_t);
175 static void fwohci_show_phypkt(struct fwohci_softc *, u_int32_t);
176 
177 /* 1 is normal debug, 2 is verbose debug, 3 is complete (packet dumps). */
178 
179 #define DPRINTF(x)      if (fwdebug) printf x
180 #define DPRINTFN(n,x)   if (fwdebug>(n)) printf x
181 int     fwdebug = 0;
182 #else
183 #define DPRINTF(x)
184 #define DPRINTFN(n,x)
185 #endif
186 
187 int
188 fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev)
189 {
190 	int i;
191 	u_int32_t val;
192 #if 0
193 	int error;
194 #endif
195 
196 	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ev,
197 	    sc->sc_sc1394.sc1394_dev.dv_xname, "intr");
198 
199 	evcnt_attach_dynamic(&sc->sc_isocnt, EVCNT_TYPE_MISC, ev,
200 	    sc->sc_sc1394.sc1394_dev.dv_xname, "iso");
201 	evcnt_attach_dynamic(&sc->sc_isopktcnt, EVCNT_TYPE_MISC, ev,
202 	    sc->sc_sc1394.sc1394_dev.dv_xname, "isopackets");
203 
204 	/*
205 	 * Wait for reset completion
206 	 */
207 	for (i = 0; i < OHCI_LOOP; i++) {
208 		val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
209 		if ((val & OHCI_HCControl_SoftReset) == 0)
210 			break;
211 		DELAY(10);
212 	}
213 
214 	/* What dialect of OHCI is this device?
215 	 */
216 	val = OHCI_CSR_READ(sc, OHCI_REG_Version);
217 	printf("%s: OHCI %u.%u", sc->sc_sc1394.sc1394_dev.dv_xname,
218 	    OHCI_Version_GET_Version(val), OHCI_Version_GET_Revision(val));
219 
220 	LIST_INIT(&sc->sc_nodelist);
221 
222 	if (fwohci_guidrom_init(sc) != 0) {
223 		printf("\n%s: fatal: no global UID ROM\n",
224 		    sc->sc_sc1394.sc1394_dev.dv_xname);
225 		return -1;
226 	}
227 
228 	printf(", %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
229 	    sc->sc_sc1394.sc1394_guid[0], sc->sc_sc1394.sc1394_guid[1],
230 	    sc->sc_sc1394.sc1394_guid[2], sc->sc_sc1394.sc1394_guid[3],
231 	    sc->sc_sc1394.sc1394_guid[4], sc->sc_sc1394.sc1394_guid[5],
232 	    sc->sc_sc1394.sc1394_guid[6], sc->sc_sc1394.sc1394_guid[7]);
233 
234 	/* Get the maximum link speed and receive size
235 	 */
236 	val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
237 	sc->sc_sc1394.sc1394_link_speed =
238 	    OHCI_BITVAL(val, OHCI_BusOptions_LinkSpd);
239 	if (sc->sc_sc1394.sc1394_link_speed < IEEE1394_SPD_MAX) {
240 		printf(", %s",
241 		    ieee1394_speeds[sc->sc_sc1394.sc1394_link_speed]);
242 	} else {
243 		printf(", unknown speed %u", sc->sc_sc1394.sc1394_link_speed);
244 	}
245 
246 	/* MaxRec is encoded as log2(max_rec_octets)-1
247 	 */
248 	sc->sc_sc1394.sc1394_max_receive =
249 	    1 << (OHCI_BITVAL(val, OHCI_BusOptions_MaxRec) + 1);
250 	printf(", %u max_rec", sc->sc_sc1394.sc1394_max_receive);
251 
252 	/*
253 	 * Count how many isochronous ctx we have.
254 	 */
255 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0);
256 	val = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntMaskClear);
257 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskClear, ~0);
258 	for (i = 0; val != 0; val >>= 1) {
259 		if (val & 0x1)
260 			i++;
261 	}
262 	sc->sc_isoctx = i;
263 	printf(", %d iso_ctx", sc->sc_isoctx);
264 
265 	printf("\n");
266 
267 #if 0
268 	error = fwohci_dnamem_alloc(sc, OHCI_CONFIG_SIZE,
269 	    OHCI_CONFIG_ALIGNMENT, &sc->sc_configrom_map,
270 	    (caddr_t *) &sc->sc_configrom, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
271 	return error;
272 #endif
273 
274 	sc->sc_dying = 0;
275 	sc->sc_nodeid = 0xffff;		/* invalid */
276 
277 	kthread_create(fwohci_create_event_thread, sc);
278 	return 0;
279 }
280 
281 static int
282 fwohci_if_setiso(struct device *self, u_int32_t channel, u_int32_t tag,
283     u_int32_t direction, void (*handler)(struct device *, struct mbuf *))
284 {
285 	struct fwohci_softc *sc = (struct fwohci_softc *)self;
286 	int retval;
287 	int s;
288 
289 	if (direction == 1) {
290 		return EIO;
291 	}
292 
293 	s = splnet();
294 	retval = fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA,
295 	    channel, tag, fwohci_if_input_iso, handler);
296 	splx(s);
297 
298 	if (!retval) {
299 		printf("%s: dummy iso handler set\n",
300 		    sc->sc_sc1394.sc1394_dev.dv_xname);
301 	} else {
302 		printf("%s: dummy iso handler cannot set\n",
303 		    sc->sc_sc1394.sc1394_dev.dv_xname);
304 	}
305 
306 	return retval;
307 }
308 
309 int
310 fwohci_intr(void *arg)
311 {
312 	struct fwohci_softc * const sc = arg;
313 	int progress = 0;
314 	u_int32_t intmask, iso;
315 
316 	for (;;) {
317 		intmask = OHCI_CSR_READ(sc, OHCI_REG_IntEventClear);
318 
319 		/*
320 		 * On a bus reset, everything except bus reset gets
321 		 * cleared.  That can't get cleared until the selfid
322 		 * phase completes (which happens outside the
323 		 * interrupt routines). So if just a bus reset is left
324 		 * in the mask and it's already in the sc_intmask,
325 		 * just return.
326 		 */
327 
328 		if ((intmask == 0) ||
329 		    (progress && (intmask == OHCI_Int_BusReset) &&
330 			(sc->sc_intmask & OHCI_Int_BusReset))) {
331 			if (progress)
332 				wakeup(fwohci_event_thread);
333 			return progress;
334 		}
335 		OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
336 		    intmask & ~OHCI_Int_BusReset);
337 #ifdef FW_DEBUG
338 		if (fwdebug > 1)
339 			fwohci_show_intr(sc, intmask);
340 #endif
341 
342 		if (intmask & OHCI_Int_BusReset) {
343 			/*
344 			 * According to OHCI spec 6.1.1 "busReset",
345 			 * All asynchronous transmit must be stopped before
346 			 * clearing BusReset.  Moreover, the BusReset
347 			 * interrupt bit should not be cleared during the
348 			 * SelfID phase.  Thus we turned off interrupt mask
349 			 * bit of BusReset instead until SelfID completion
350 			 * or SelfID timeout.
351 			 */
352 			intmask &= OHCI_Int_SelfIDComplete;
353 			OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear,
354 			    OHCI_Int_BusReset);
355 			sc->sc_intmask = OHCI_Int_BusReset;
356 		}
357 		sc->sc_intmask |= intmask;
358 
359 		if (intmask & OHCI_Int_IsochTx) {
360 			iso = OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear);
361 			OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntEventClear, iso);
362 		}
363 		if (intmask & OHCI_Int_IsochRx) {
364 #if NO_THREAD
365 			int i;
366 			int asyncstream = 0;
367 #endif
368 
369 			iso = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear);
370 			OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, iso);
371 #if NO_THREAD
372 			for (i = 0; i < sc->sc_isoctx; i++) {
373 				if ((iso & (1<<i)) && sc->sc_ctx_ir[i] != NULL) {
374 					if (sc->sc_ctx_ir[i]->fc_type == FWOHCI_CTX_ISO_SINGLE) {
375 						asyncstream |= (1 << i);
376 						continue;
377 					}
378 					bus_dmamap_sync(sc->sc_dmat,
379 					    sc->sc_ddmamap,
380 					    0, sizeof(struct fwohci_desc) * sc->sc_descsize,
381 					    BUS_DMASYNC_PREREAD);
382 					sc->sc_isocnt.ev_count++;
383 
384 					fwohci_ir_input(sc, sc->sc_ctx_ir[i]);
385 				}
386 			}
387 			if (asyncstream != 0) {
388 				sc->sc_iso |= asyncstream;
389 			} else {
390 				/* all iso intr is pure isochronous */
391 				sc->sc_intmask &= ~OHCI_Int_IsochRx;
392 			}
393 #else
394 			sc->sc_iso |= iso;
395 #endif /* NO_THREAD */
396 		}
397 
398 		if (!progress) {
399 			sc->sc_intrcnt.ev_count++;
400 			progress = 1;
401 		}
402 	}
403 }
404 
405 static void
406 fwohci_create_event_thread(void *arg)
407 {
408 	struct fwohci_softc  *sc = arg;
409 
410 	if (kthread_create1(fwohci_thread_init, sc, &sc->sc_event_thread, "%s",
411 	    sc->sc_sc1394.sc1394_dev.dv_xname)) {
412 		printf("%s: unable to create event thread\n",
413 		    sc->sc_sc1394.sc1394_dev.dv_xname);
414 		panic("fwohci_create_event_thread");
415 	}
416 }
417 
418 static void
419 fwohci_thread_init(void *arg)
420 {
421 	struct fwohci_softc *sc = arg;
422 	int i;
423 
424 	/*
425 	 * Allocate descriptors
426 	 */
427 	if (fwohci_desc_alloc(sc)) {
428 		printf("%s: not enabling interrupts\n",
429 		    sc->sc_sc1394.sc1394_dev.dv_xname);
430 		kthread_exit(1);
431 	}
432 
433 	/*
434 	 * Enable Link Power
435 	 */
436 
437 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS);
438 
439 	/*
440 	 * Allocate DMA Context
441 	 */
442 	fwohci_ctx_alloc(sc, &sc->sc_ctx_arrq, OHCI_BUF_ARRQ_CNT,
443 	    OHCI_CTX_ASYNC_RX_REQUEST, FWOHCI_CTX_ASYNC);
444 	fwohci_ctx_alloc(sc, &sc->sc_ctx_arrs, OHCI_BUF_ARRS_CNT,
445 	    OHCI_CTX_ASYNC_RX_RESPONSE, FWOHCI_CTX_ASYNC);
446 	fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, 0, OHCI_CTX_ASYNC_TX_REQUEST,
447 	    FWOHCI_CTX_ASYNC);
448 	fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, 0, OHCI_CTX_ASYNC_TX_RESPONSE,
449 	    FWOHCI_CTX_ASYNC);
450 	sc->sc_ctx_ir = malloc(sizeof(sc->sc_ctx_ir[0]) * sc->sc_isoctx,
451 	    M_DEVBUF, M_WAITOK);
452 	for (i = 0; i < sc->sc_isoctx; i++)
453 		sc->sc_ctx_ir[i] = NULL;
454 
455 	/*
456 	 * Allocate buffer for configuration ROM and SelfID buffer
457 	 */
458 	fwohci_buf_alloc(sc, &sc->sc_buf_cnfrom);
459 	fwohci_buf_alloc(sc, &sc->sc_buf_selfid);
460 
461 	callout_init(&sc->sc_selfid_callout);
462 
463 	sc->sc_sc1394.sc1394_ifinreg = fwohci_if_inreg;
464 	sc->sc_sc1394.sc1394_ifoutput = fwohci_if_output;
465 	sc->sc_sc1394.sc1394_ifsetiso = fwohci_if_setiso;
466 
467 	/*
468 	 * establish hooks for shutdown and suspend/resume
469 	 */
470 	sc->sc_shutdownhook = shutdownhook_establish(fwohci_shutdown, sc);
471 	sc->sc_powerhook = powerhook_establish(fwohci_power, sc);
472 
473 	sc->sc_sc1394.sc1394_if = config_found(&sc->sc_sc1394.sc1394_dev, "fw",
474 	    fwohci_print);
475 
476 	/* Main loop. It's not coming back normally. */
477 
478 	fwohci_event_thread(sc);
479 
480 	kthread_exit(0);
481 }
482 
483 static void
484 fwohci_event_thread(struct fwohci_softc *sc)
485 {
486 	int i, s;
487 	u_int32_t intmask, iso;
488 
489 	s = splbio();
490 
491 	/*
492 	 * Initialize hardware registers.
493 	 */
494 
495 	fwohci_hw_init(sc);
496 
497 	/* Initial Bus Reset */
498 	fwohci_phy_busreset(sc);
499 	splx(s);
500 
501 	while (!sc->sc_dying) {
502 		s = splbio();
503 		intmask = sc->sc_intmask;
504 		if (intmask == 0) {
505 			tsleep(fwohci_event_thread, PZERO, "fwohciev", 0);
506 			splx(s);
507 			continue;
508 		}
509 		sc->sc_intmask = 0;
510 		splx(s);
511 
512 		if (intmask & OHCI_Int_BusReset) {
513 			fwohci_buf_stop_tx(sc);
514 			if (sc->sc_uidtbl != NULL) {
515 				free(sc->sc_uidtbl, M_DEVBUF);
516 				sc->sc_uidtbl = NULL;
517 			}
518 
519 			callout_reset(&sc->sc_selfid_callout,
520 			    OHCI_SELFID_TIMEOUT,
521 			    (void (*)(void *))fwohci_phy_busreset, sc);
522 			sc->sc_nodeid = 0xffff;	/* indicate invalid */
523 			sc->sc_rootid = 0;
524 			sc->sc_irmid = IEEE1394_BCAST_PHY_ID;
525 		}
526 		if (intmask & OHCI_Int_SelfIDComplete) {
527 			s = splbio();
528 			OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
529 			    OHCI_Int_BusReset);
530 			OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet,
531 			    OHCI_Int_BusReset);
532 			splx(s);
533 			callout_stop(&sc->sc_selfid_callout);
534 			if (fwohci_selfid_input(sc) == 0) {
535 				fwohci_buf_start_rx(sc);
536 				fwohci_uid_collect(sc);
537 			}
538 		}
539 		if (intmask & OHCI_Int_ReqTxComplete)
540 			fwohci_at_done(sc, sc->sc_ctx_atrq, 0);
541 		if (intmask & OHCI_Int_RespTxComplete)
542 			fwohci_at_done(sc, sc->sc_ctx_atrs, 0);
543 		if (intmask & OHCI_Int_RQPkt)
544 			fwohci_arrq_input(sc, sc->sc_ctx_arrq);
545 		if (intmask & OHCI_Int_RSPkt)
546 			fwohci_arrs_input(sc, sc->sc_ctx_arrs);
547 		if (intmask & OHCI_Int_IsochRx) {
548 			s = splbio();
549 			iso = sc->sc_iso;
550 			sc->sc_iso = 0;
551 			splx(s);
552 			for (i = 0; i < sc->sc_isoctx; i++) {
553 				if ((iso & (1 << i)) &&
554 				    sc->sc_ctx_ir[i] != NULL) {
555 					fwohci_ir_input(sc, sc->sc_ctx_ir[i]);
556 					sc->sc_isocnt.ev_count++;
557 				}
558 			}
559 		}
560 	}
561 }
562 
563 #if 0
564 static int
565 fwohci_dnamem_alloc(struct fwohci_softc *sc, int size, int alignment,
566     bus_dmamap_t *mapp, caddr_t *kvap, int flags)
567 {
568 	bus_dma_segment_t segs[1];
569 	int error, nsegs, steps;
570 
571 	steps = 0;
572 	error = bus_dmamem_alloc(sc->sc_dmat, size, alignment, alignment,
573 	    segs, 1, &nsegs, flags);
574 	if (error)
575 		goto cleanup;
576 
577 	steps = 1;
578 	error = bus_dmamem_map(sc->sc_dmat, segs, nsegs, segs[0].ds_len,
579 	    kvap, flags);
580 	if (error)
581 		goto cleanup;
582 
583 	if (error == 0)
584 		error = bus_dmamap_create(sc->sc_dmat, size, 1, alignment,
585 		    size, flags, mapp);
586 	if (error)
587 		goto cleanup;
588 	if (error == 0)
589 		error = bus_dmamap_load(sc->sc_dmat, *mapp, *kvap, size, NULL,
590 		    flags);
591 	if (error)
592 		goto cleanup;
593 
594  cleanup:
595 	switch (steps) {
596 	case 1:
597 		bus_dmamem_free(sc->sc_dmat, segs, nsegs);
598 	}
599 
600 	return error;
601 }
602 #endif
603 
604 int
605 fwohci_print(void *aux, const char *pnp)
606 {
607 	char *name = aux;
608 
609 	if (pnp)
610 		printf("%s at %s", name, pnp);
611 
612 	return QUIET;
613 }
614 
615 static void
616 fwohci_hw_init(struct fwohci_softc *sc)
617 {
618 	int i;
619 	u_int32_t val;
620 
621 	/*
622 	 * Software Reset.
623 	 */
624 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset);
625 	for (i = 0; i < OHCI_LOOP; i++) {
626 		val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
627 		if ((val & OHCI_HCControl_SoftReset) == 0)
628 			break;
629 		DELAY(10);
630 	}
631 
632 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS);
633 
634 	/*
635 	 * First, initilize CSRs with undefined value to default settings.
636 	 */
637 	val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
638 	val |= OHCI_BusOptions_ISC | OHCI_BusOptions_CMC;
639 #if 0
640 	val |= OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC;
641 #else
642 	val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC);
643 #endif
644 	OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val);
645 	for (i = 0; i < sc->sc_isoctx; i++) {
646 		OHCI_SYNC_RX_DMA_WRITE(sc, i, OHCI_SUBREG_ContextControlClear,
647 		    ~0);
648 	}
649 	OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear, ~0);
650 
651 	fwohci_configrom_init(sc);
652 	fwohci_selfid_init(sc);
653 	fwohci_buf_init_rx(sc);
654 	fwohci_csr_init(sc);
655 
656 	/*
657 	 * Final CSR settings.
658 	 */
659 	OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet,
660 	    OHCI_LinkControl_CycleTimerEnable |
661 	    OHCI_LinkControl_RcvSelfID | OHCI_LinkControl_RcvPhyPkt);
662 
663 	OHCI_CSR_WRITE(sc, OHCI_REG_ATRetries, 0x00000888);	/*XXX*/
664 
665 	/* clear receive filter */
666 	OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiClear, ~0);
667 	OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoClear, ~0);
668 	OHCI_CSR_WRITE(sc, OHCI_REG_AsynchronousRequestFilterHiSet, 0x80000000);
669 
670 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear,
671 	    OHCI_HCControl_NoByteSwapData | OHCI_HCControl_APhyEnhanceEnable);
672 #if BYTE_ORDER == BIG_ENDIAN
673 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet,
674 	    OHCI_HCControl_NoByteSwapData);
675 #endif
676 
677 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, ~0);
678 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset |
679 	    OHCI_Int_SelfIDComplete | OHCI_Int_IsochRx | OHCI_Int_IsochTx |
680 	    OHCI_Int_RSPkt | OHCI_Int_RQPkt | OHCI_Int_ARRS | OHCI_Int_ARRQ |
681 	    OHCI_Int_RespTxComplete | OHCI_Int_ReqTxComplete);
682 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_CycleTooLong |
683 	    OHCI_Int_UnrecoverableError | OHCI_Int_CycleInconsistent |
684 	    OHCI_Int_LockRespErr | OHCI_Int_PostedWriteErr);
685 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskSet, ~0);
686 	OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0);
687 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_MasterEnable);
688 
689 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LinkEnable);
690 
691 	/*
692 	 * Start the receivers
693 	 */
694 	fwohci_buf_start_rx(sc);
695 }
696 
697 static void
698 fwohci_power(int why, void *arg)
699 {
700 	struct fwohci_softc *sc = arg;
701 	int s;
702 
703 	s = splbio();
704 	switch (why) {
705 	case PWR_SUSPEND:
706 	case PWR_STANDBY:
707 		fwohci_shutdown(sc);
708 		break;
709 	case PWR_RESUME:
710 		fwohci_hw_init(sc);
711 		fwohci_phy_busreset(sc);
712 		break;
713 	case PWR_SOFTSUSPEND:
714 	case PWR_SOFTSTANDBY:
715 	case PWR_SOFTRESUME:
716 		break;
717 	}
718 	splx(s);
719 }
720 
721 static void
722 fwohci_shutdown(void *arg)
723 {
724 	struct fwohci_softc *sc = arg;
725 	u_int32_t val;
726 
727 	callout_stop(&sc->sc_selfid_callout);
728 	/* disable all interrupt */
729 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, OHCI_Int_MasterEnable);
730 	fwohci_buf_stop_tx(sc);
731 	fwohci_buf_stop_rx(sc);
732 	val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
733 	val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_ISC |
734 		OHCI_BusOptions_CMC | OHCI_BusOptions_IRMC);
735 	OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val);
736 	fwohci_phy_busreset(sc);
737 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LinkEnable);
738 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LPS);
739 	OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset);
740 }
741 
742 /*
743  * COMMON FUNCTIONS
744  */
745 
746 /*
747  * read the PHY Register.
748  */
749 static u_int8_t
750 fwohci_phy_read(struct fwohci_softc *sc, u_int8_t reg)
751 {
752 	int i;
753 	u_int32_t val;
754 
755 	OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl,
756 	    OHCI_PhyControl_RdReg | (reg << OHCI_PhyControl_RegAddr_BITPOS));
757 	for (i = 0; i < OHCI_LOOP; i++) {
758 		if (OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
759 		    OHCI_PhyControl_RdDone)
760 			break;
761 		DELAY(10);
762 	}
763 	val = OHCI_CSR_READ(sc, OHCI_REG_PhyControl);
764 	return (val & OHCI_PhyControl_RdData) >> OHCI_PhyControl_RdData_BITPOS;
765 }
766 
767 /*
768  * write the PHY Register.
769  */
770 static void
771 fwohci_phy_write(struct fwohci_softc *sc, u_int8_t reg, u_int8_t val)
772 {
773 	int i;
774 
775 	OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl, OHCI_PhyControl_WrReg |
776 	    (reg << OHCI_PhyControl_RegAddr_BITPOS) |
777 	    (val << OHCI_PhyControl_WrData_BITPOS));
778 	for (i = 0; i < OHCI_LOOP; i++) {
779 		if (!(OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
780 		    OHCI_PhyControl_WrReg))
781 			break;
782 		DELAY(10);
783 	}
784 }
785 
786 /*
787  * Initiate Bus Reset
788  */
789 static void
790 fwohci_phy_busreset(struct fwohci_softc *sc)
791 {
792 	int s;
793 	u_int8_t val;
794 
795 	s = splbio();
796 	OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
797 	    OHCI_Int_BusReset | OHCI_Int_SelfIDComplete);
798 	OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset);
799 	callout_stop(&sc->sc_selfid_callout);
800 	val = fwohci_phy_read(sc, 1);
801 	val = (val & 0x80) |			/* preserve RHB (force root) */
802 	    0x40 |				/* Initiate Bus Reset */
803 	    0x3f;				/* default GAP count */
804 	fwohci_phy_write(sc, 1, val);
805 	splx(s);
806 }
807 
808 /*
809  * PHY Packet
810  */
811 static void
812 fwohci_phy_input(struct fwohci_softc *sc, struct fwohci_pkt *pkt)
813 {
814 	u_int32_t val;
815 
816 	val = pkt->fp_hdr[1];
817 	if (val != ~pkt->fp_hdr[2]) {
818 		if (val == 0 && ((*pkt->fp_trail & 0x001f0000) >> 16) ==
819 		    OHCI_CTXCTL_EVENT_BUS_RESET) {
820 			DPRINTFN(1, ("fwohci_phy_input: BusReset: 0x%08x\n",
821 			    pkt->fp_hdr[2]));
822 		} else {
823 			printf("%s: phy packet corrupted (0x%08x, 0x%08x)\n",
824 			    sc->sc_sc1394.sc1394_dev.dv_xname, val,
825 			    pkt->fp_hdr[2]);
826 		}
827 		return;
828 	}
829 #ifdef FW_DEBUG
830 	if (fwdebug > 1)
831 		fwohci_show_phypkt(sc, val);
832 #endif
833 }
834 
835 /*
836  * Descriptor for context DMA.
837  */
838 static int
839 fwohci_desc_alloc(struct fwohci_softc *sc)
840 {
841 	int error, mapsize, dsize;
842 
843 	/*
844 	 * allocate descriptor buffer
845 	 */
846 
847 	sc->sc_descsize = OHCI_BUF_ARRQ_CNT + OHCI_BUF_ARRS_CNT +
848 	    OHCI_BUF_ATRQ_CNT + OHCI_BUF_ATRS_CNT +
849 	    OHCI_BUF_IR_CNT * sc->sc_isoctx + 2;
850 	dsize = sizeof(struct fwohci_desc) * sc->sc_descsize;
851 	mapsize = howmany(sc->sc_descsize, NBBY);
852 	sc->sc_descmap = malloc(mapsize, M_DEVBUF, M_WAITOK);
853 	memset(sc->sc_descmap, 0, mapsize);
854 
855 	if ((error = bus_dmamem_alloc(sc->sc_dmat, dsize, PAGE_SIZE, 0,
856 	    &sc->sc_dseg, 1, &sc->sc_dnseg, 0)) != 0) {
857 		printf("%s: unable to allocate descriptor buffer, error = %d\n",
858 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
859 		goto fail_0;
860 	}
861 
862 	if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg,
863 	    dsize, (caddr_t *)&sc->sc_desc, BUS_DMA_COHERENT | BUS_DMA_WAITOK))
864 	    != 0) {
865 		printf("%s: unable to map descriptor buffer, error = %d\n",
866 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
867 		goto fail_1;
868 	}
869 
870 	if ((error = bus_dmamap_create(sc->sc_dmat, dsize, sc->sc_dnseg,
871 	    dsize, 0, BUS_DMA_WAITOK, &sc->sc_ddmamap)) != 0) {
872 		printf("%s: unable to create descriptor buffer DMA map, "
873 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
874 		goto fail_2;
875 	}
876 
877 	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap, sc->sc_desc,
878 	    dsize, NULL, BUS_DMA_WAITOK)) != 0) {
879 		printf("%s: unable to load descriptor buffer DMA map, "
880 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
881 		goto fail_3;
882 	}
883 
884 	return 0;
885 
886   fail_3:
887 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
888   fail_2:
889 	bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_desc, dsize);
890   fail_1:
891 	bus_dmamem_free(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg);
892   fail_0:
893 	return error;
894 }
895 
896 static struct fwohci_desc *
897 fwohci_desc_get(struct fwohci_softc *sc, int ndesc)
898 {
899 	int i, n;
900 
901 	for (n = 0; n <= sc->sc_descsize - ndesc; n++) {
902 		for (i = 0; ; i++) {
903 			if (i == ndesc) {
904 				for (i = 0; i < ndesc; i++)
905 					setbit(sc->sc_descmap, n + i);
906 				return sc->sc_desc + n;
907 			}
908 			if (isset(sc->sc_descmap, n + i))
909 				break;
910 		}
911 	}
912 	return NULL;
913 }
914 
915 static void
916 fwohci_desc_put(struct fwohci_softc *sc, struct fwohci_desc *fd, int ndesc)
917 {
918 	int i, n;
919 
920 	n = fd - sc->sc_desc;
921 	for (i = 0; i < ndesc; i++, n++) {
922 #ifdef DIAGNOSTIC
923 		if (isclr(sc->sc_descmap, n))
924 			panic("fwohci_desc_put: duplicated free");
925 #endif
926 		clrbit(sc->sc_descmap, n);
927 	}
928 }
929 
930 /*
931  * Asyncronous/Isochronous Transmit/Receive Context
932  */
933 static int
934 fwohci_ctx_alloc(struct fwohci_softc *sc, struct fwohci_ctx **fcp,
935     int bufcnt, int ctx, int ctxtype)
936 {
937 	int i, error;
938 	struct fwohci_ctx *fc;
939 	struct fwohci_buf *fb;
940 	struct fwohci_desc *fd;
941 	int buf2cnt;
942 
943 	fc = malloc(sizeof(*fc) + sizeof(*fb) * bufcnt, M_DEVBUF, M_WAITOK);
944 	memset(fc, 0, sizeof(*fc) + sizeof(*fb) * bufcnt);
945 	LIST_INIT(&fc->fc_handler);
946 	TAILQ_INIT(&fc->fc_buf);
947 	fc->fc_ctx = ctx;
948 	fc->fc_bufcnt = bufcnt;
949 	fb = (struct fwohci_buf *)&fc[1];
950 #if DOUBLEBUF
951 	TAILQ_INIT(&fc->fc_buf2); /* for isochronous */
952 	if (ctxtype == FWOHCI_CTX_ISO_MULTI) {
953 		buf2cnt = bufcnt/2;
954 		bufcnt -= buf2cnt;
955 		if (buf2cnt == 0) {
956 			panic("cannot allocate iso buffer");
957 		}
958 	}
959 #endif
960 	for (i = 0; i < bufcnt; i++, fb++) {
961 		if ((error = fwohci_buf_alloc(sc, fb)) != 0)
962 			goto fail;
963 		if ((fd = fwohci_desc_get(sc, 1)) == NULL) {
964 			error = ENOBUFS;
965 			goto fail;
966 		}
967 		fb->fb_desc = fd;
968 		fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
969 		    ((caddr_t)fd - (caddr_t)sc->sc_desc);
970 		fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS |
971 		    OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH;
972 		fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len;
973 		fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr;
974 		TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
975 	}
976 #if DOUBLEBUF
977 	if (ctxtype == FWOHCI_CTX_ISO_MULTI) {
978 		for (i = bufcnt; i < bufcnt + buf2cnt; i++, fb++) {
979 			if ((error = fwohci_buf_alloc(sc, fb)) != 0)
980 				goto fail;
981 			if ((fd = fwohci_desc_get(sc, 1)) == NULL) {
982 				error = ENOBUFS;
983 				goto fail;
984 			}
985 			fb->fb_desc = fd;
986 			fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
987 			    ((caddr_t)fd - (caddr_t)sc->sc_desc);
988 			bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
989 			    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
990 			    BUS_DMASYNC_PREWRITE);
991 			fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS |
992 			    OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH;
993 			fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len;
994 			fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr;
995 			TAILQ_INSERT_TAIL(&fc->fc_buf2, fb, fb_list);
996 			bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
997 			    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
998 			    BUS_DMASYNC_POSTWRITE);
999 		}
1000 	}
1001 #endif /* DOUBLEBUF */
1002 	fc->fc_type = ctxtype;
1003 	*fcp = fc;
1004 	return 0;
1005 
1006   fail:
1007 	while (i-- > 0) {
1008 		fb--;
1009 		if (fb->fb_desc)
1010 			fwohci_desc_put(sc, fb->fb_desc, 1);
1011 		fwohci_buf_free(sc, fb);
1012 	}
1013 	free(fc, M_DEVBUF);
1014 	return error;
1015 }
1016 
1017 static void
1018 fwohci_ctx_free(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1019 {
1020 	struct fwohci_buf *fb;
1021 	struct fwohci_handler *fh;
1022 
1023 	while ((fh = LIST_FIRST(&fc->fc_handler)) != NULL)
1024 		fwohci_handler_set(sc, fh->fh_tcode, fh->fh_key1, fh->fh_key2,
1025 		    NULL, NULL);
1026 	while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1027 		TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
1028 		if (fb->fb_desc)
1029 			fwohci_desc_put(sc, fb->fb_desc, 1);
1030 		fwohci_buf_free(sc, fb);
1031 	}
1032 #if DOUBLEBUF
1033 	while ((fb = TAILQ_FIRST(&fc->fc_buf2)) != NULL) {
1034 		TAILQ_REMOVE(&fc->fc_buf2, fb, fb_list);
1035 		if (fb->fb_desc)
1036 			fwohci_desc_put(sc, fb->fb_desc, 1);
1037 		fwohci_buf_free(sc, fb);
1038 	}
1039 #endif /* DOUBLEBUF */
1040 	free(fc, M_DEVBUF);
1041 }
1042 
1043 static void
1044 fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1045 {
1046 	struct fwohci_buf *fb, *nfb;
1047 	struct fwohci_desc *fd;
1048 	struct fwohci_handler *fh;
1049 	int n;
1050 
1051 	for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; fb = nfb) {
1052 		nfb = TAILQ_NEXT(fb, fb_list);
1053 		fb->fb_off = 0;
1054 		fd = fb->fb_desc;
1055 		fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
1056 		fd->fd_rescount = fd->fd_reqcount;
1057 	}
1058 
1059 #if DOUBLEBUF
1060 	for (fb = TAILQ_FIRST(&fc->fc_buf2); fb != NULL; fb = nfb) {
1061 		bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
1062 		    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
1063 		    BUS_DMASYNC_PREWRITE);
1064 		nfb = TAILQ_NEXT(fb, fb_list);
1065 		fb->fb_off = 0;
1066 		fd = fb->fb_desc;
1067 		fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
1068 		fd->fd_rescount = fd->fd_reqcount;
1069 		bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
1070 		    (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
1071 		    BUS_DMASYNC_POSTWRITE);
1072 	}
1073 #endif /* DOUBLEBUF */
1074 
1075 	n = fc->fc_ctx;
1076 	fb = TAILQ_FIRST(&fc->fc_buf);
1077 	if (fc->fc_type != FWOHCI_CTX_ASYNC) {
1078 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
1079 		    fb->fb_daddr | 1);
1080 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear,
1081 		    OHCI_CTXCTL_RX_BUFFER_FILL |
1082 		    OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE |
1083 		    OHCI_CTXCTL_RX_MULTI_CHAN_MODE |
1084 		    OHCI_CTXCTL_RX_DUAL_BUFFER_MODE);
1085 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet,
1086 		    OHCI_CTXCTL_RX_ISOCH_HEADER);
1087 		if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) {
1088 			OHCI_SYNC_RX_DMA_WRITE(sc, n,
1089 			    OHCI_SUBREG_ContextControlSet,
1090 			    OHCI_CTXCTL_RX_BUFFER_FILL);
1091 		}
1092 		fh = LIST_FIRST(&fc->fc_handler);
1093 		OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextMatch,
1094 		    (OHCI_CTXMATCH_TAG0 << fh->fh_key2) | fh->fh_key1);
1095 	} else {
1096 		OHCI_ASYNC_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
1097 		    fb->fb_daddr | 1);
1098 	}
1099 }
1100 
1101 /*
1102  * DMA data buffer
1103  */
1104 static int
1105 fwohci_buf_alloc(struct fwohci_softc *sc, struct fwohci_buf *fb)
1106 {
1107 	int error;
1108 
1109 	if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
1110 	    PAGE_SIZE, &fb->fb_seg, 1, &fb->fb_nseg, BUS_DMA_WAITOK)) != 0) {
1111 		printf("%s: unable to allocate buffer, error = %d\n",
1112 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
1113 		goto fail_0;
1114 	}
1115 
1116 	if ((error = bus_dmamem_map(sc->sc_dmat, &fb->fb_seg,
1117 	    fb->fb_nseg, PAGE_SIZE, &fb->fb_buf, BUS_DMA_WAITOK)) != 0) {
1118 		printf("%s: unable to map buffer, error = %d\n",
1119 		    sc->sc_sc1394.sc1394_dev.dv_xname, error);
1120 		goto fail_1;
1121 	}
1122 
1123 	if ((error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, fb->fb_nseg,
1124 	    PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) {
1125 		printf("%s: unable to create buffer DMA map, "
1126 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
1127 		    error);
1128 		goto fail_2;
1129 	}
1130 
1131 	if ((error = bus_dmamap_load(sc->sc_dmat, fb->fb_dmamap,
1132 	    fb->fb_buf, PAGE_SIZE, NULL, BUS_DMA_WAITOK)) != 0) {
1133 		printf("%s: unable to load buffer DMA map, "
1134 		    "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
1135 		    error);
1136 		goto fail_3;
1137 	}
1138 
1139 	return 0;
1140 
1141 	bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
1142   fail_3:
1143 	bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1144   fail_2:
1145 	bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
1146   fail_1:
1147 	bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
1148   fail_0:
1149 	return error;
1150 }
1151 
1152 static void
1153 fwohci_buf_free(struct fwohci_softc *sc, struct fwohci_buf *fb)
1154 {
1155 
1156 	bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
1157 	bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1158 	bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
1159 	bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
1160 }
1161 
1162 static void
1163 fwohci_buf_init_rx(struct fwohci_softc *sc)
1164 {
1165 	int i;
1166 
1167 	/*
1168 	 * Initialize for Asynchronous Receive Queue.
1169 	 */
1170 	fwohci_ctx_init(sc, sc->sc_ctx_arrq);
1171 	fwohci_ctx_init(sc, sc->sc_ctx_arrs);
1172 
1173 	/*
1174 	 * Initialize for Isochronous Receive Queue.
1175 	 */
1176 	for (i = 0; i < sc->sc_isoctx; i++) {
1177 		if (sc->sc_ctx_ir[i] != NULL)
1178 			fwohci_ctx_init(sc, sc->sc_ctx_ir[i]);
1179 	}
1180 }
1181 
1182 static void
1183 fwohci_buf_start_rx(struct fwohci_softc *sc)
1184 {
1185 	int i;
1186 
1187 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
1188 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1189 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
1190 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1191 	for (i = 0; i < sc->sc_isoctx; i++) {
1192 		if (sc->sc_ctx_ir[i] != NULL)
1193 			OHCI_SYNC_RX_DMA_WRITE(sc, i,
1194 			    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1195 	}
1196 }
1197 
1198 static void
1199 fwohci_buf_stop_tx(struct fwohci_softc *sc)
1200 {
1201 	int i;
1202 
1203 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_REQUEST,
1204 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1205 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
1206 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1207 
1208 	/*
1209 	 * Make sure the transmitter is stopped.
1210 	 */
1211 	for (i = 0; i < OHCI_LOOP; i++) {
1212 		DELAY(10);
1213 		if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
1214 		    OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
1215 			continue;
1216 		if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
1217 		    OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
1218 			continue;
1219 		break;
1220 	}
1221 
1222 	/*
1223 	 * Initialize for Asynchronous Transmit Queue.
1224 	 */
1225 	fwohci_at_done(sc, sc->sc_ctx_atrq, 1);
1226 	fwohci_at_done(sc, sc->sc_ctx_atrs, 1);
1227 }
1228 
1229 static void
1230 fwohci_buf_stop_rx(struct fwohci_softc *sc)
1231 {
1232 	int i;
1233 
1234 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
1235 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1236 	OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
1237 	    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1238 	for (i = 0; i < sc->sc_isoctx; i++) {
1239 		OHCI_SYNC_RX_DMA_WRITE(sc, i,
1240 		    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1241 	}
1242 }
1243 
1244 static void
1245 fwohci_buf_next(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1246 {
1247 	struct fwohci_buf *fb, *tfb;
1248 
1249 #if DOUBLEBUF
1250 	if (fc->fc_type != FWOHCI_CTX_ISO_MULTI) {
1251 #endif
1252 		while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1253 			if (fc->fc_type) {
1254 				if (fb->fb_off == 0)
1255 					break;
1256 			} else {
1257 				if (fb->fb_off != fb->fb_desc->fd_reqcount ||
1258 				    fb->fb_desc->fd_rescount != 0)
1259 					break;
1260 			}
1261 			TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
1262 			fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
1263 			fb->fb_off = 0;
1264 			fb->fb_desc->fd_branch = 0;
1265 			tfb = TAILQ_LAST(&fc->fc_buf, fwohci_buf_s);
1266 			tfb->fb_desc->fd_branch = fb->fb_daddr | 1;
1267 			TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
1268 		}
1269 #if DOUBLEBUF
1270 	} else {
1271 		struct fwohci_buf_s fctmp;
1272 
1273 		/* cleaning buffer */
1274 		for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL;
1275 		     fb = TAILQ_NEXT(fb, fb_list)) {
1276 			fb->fb_off = 0;
1277 			fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
1278 		}
1279 
1280 		/* rotating buffer */
1281 		fctmp = fc->fc_buf;
1282 		fc->fc_buf = fc->fc_buf2;
1283 		fc->fc_buf2 = fctmp;
1284 	}
1285 #endif
1286 }
1287 
1288 static int
1289 fwohci_buf_pktget(struct fwohci_softc *sc, struct fwohci_buf **fbp, caddr_t *pp,
1290     int len)
1291 {
1292 	struct fwohci_buf *fb;
1293 	struct fwohci_desc *fd;
1294 	int bufend;
1295 
1296 	fb = *fbp;
1297   again:
1298 	fd = fb->fb_desc;
1299 	DPRINTFN(1, ("fwohci_buf_pktget: desc %ld, off %d, req %d, res %d,"
1300 	    " len %d, avail %d\n", (long)(fd - sc->sc_desc), fb->fb_off,
1301 	    fd->fd_reqcount, fd->fd_rescount, len,
1302 	    fd->fd_reqcount - fd->fd_rescount - fb->fb_off));
1303 	bufend = fd->fd_reqcount - fd->fd_rescount;
1304 	if (fb->fb_off >= bufend) {
1305 		DPRINTFN(5, ("buf %x finish req %d res %d off %d ",
1306 		    fb->fb_desc->fd_data, fd->fd_reqcount, fd->fd_rescount,
1307 		    fb->fb_off));
1308 		if (fd->fd_rescount == 0) {
1309 			*fbp = fb = TAILQ_NEXT(fb, fb_list);
1310 			if (fb != NULL)
1311 				goto again;
1312 		}
1313 		return 0;
1314 	}
1315 	if (fb->fb_off + len > bufend)
1316 		len = bufend - fb->fb_off;
1317 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
1318 	    BUS_DMASYNC_POSTREAD);
1319 	*pp = fb->fb_buf + fb->fb_off;
1320 	fb->fb_off += roundup(len, 4);
1321 	return len;
1322 }
1323 
1324 static int
1325 fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1326     struct fwohci_pkt *pkt)
1327 {
1328 	caddr_t p;
1329 	struct fwohci_buf *fb;
1330 	int len, count, i;
1331 
1332 	memset(pkt, 0, sizeof(*pkt));
1333 	pkt->fp_uio.uio_iov = pkt->fp_iov;
1334 	pkt->fp_uio.uio_rw = UIO_WRITE;
1335 	pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
1336 
1337 	/* get first quadlet */
1338 	fb = TAILQ_FIRST(&fc->fc_buf);
1339 	count = 4;
1340 	len = fwohci_buf_pktget(sc, &fb, &p, count);
1341 	if (len <= 0) {
1342 		DPRINTFN(1, ("fwohci_buf_input: no input for %d\n",
1343 		    fc->fc_ctx));
1344 		return 0;
1345 	}
1346 	pkt->fp_hdr[0] = *(u_int32_t *)p;
1347 	pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
1348 	switch (pkt->fp_tcode) {
1349 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
1350 	case IEEE1394_TCODE_READ_RESP_QUAD:
1351 		pkt->fp_hlen = 12;
1352 		pkt->fp_dlen = 4;
1353 		break;
1354 	case IEEE1394_TCODE_READ_REQ_BLOCK:
1355 		pkt->fp_hlen = 16;
1356 		pkt->fp_dlen = 0;
1357 		break;
1358 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1359 	case IEEE1394_TCODE_READ_RESP_BLOCK:
1360 	case IEEE1394_TCODE_LOCK_REQ:
1361 	case IEEE1394_TCODE_LOCK_RESP:
1362 		pkt->fp_hlen = 16;
1363 		break;
1364 	case IEEE1394_TCODE_STREAM_DATA:
1365 #ifdef DIAGNOSTIC
1366 		if (fc->fc_type == FWOHCI_CTX_ISO_MULTI)
1367 #endif
1368 		{
1369 			pkt->fp_hlen = 4;
1370 			pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
1371 			DPRINTFN(5, ("[%d]", pkt->fp_dlen));
1372 			break;
1373 		}
1374 #ifdef DIAGNOSTIC
1375 		else {
1376 			printf("fwohci_buf_input: bad tcode: STREAM_DATA\n");
1377 			return 0;
1378 		}
1379 #endif
1380 	default:
1381 		pkt->fp_hlen = 12;
1382 		pkt->fp_dlen = 0;
1383 		break;
1384 	}
1385 
1386 	/* get header */
1387 	while (count < pkt->fp_hlen) {
1388 		len = fwohci_buf_pktget(sc, &fb, &p, pkt->fp_hlen - count);
1389 		if (len == 0) {
1390 			printf("fwohci_buf_input: malformed input 1: %d\n",
1391 			    pkt->fp_hlen - count);
1392 			return 0;
1393 		}
1394 		memcpy((caddr_t)pkt->fp_hdr + count, p, len);
1395 		count += len;
1396 	}
1397 	if (pkt->fp_hlen == 16 &&
1398 	    pkt->fp_tcode != IEEE1394_TCODE_READ_REQ_BLOCK)
1399 		pkt->fp_dlen = pkt->fp_hdr[3] >> 16;
1400 	DPRINTFN(1, ("fwohci_buf_input: tcode=0x%x, hlen=%d, dlen=%d\n",
1401 	    pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
1402 
1403 	/* get data */
1404 	count = 0;
1405 	i = 0;
1406 	while (count < pkt->fp_dlen) {
1407 		len = fwohci_buf_pktget(sc, &fb,
1408 		    (caddr_t *)&pkt->fp_iov[i].iov_base,
1409 		    pkt->fp_dlen - count);
1410 		if (len == 0) {
1411 			printf("fwohci_buf_input: malformed input 2: %d\n",
1412 			    pkt->fp_dlen - count);
1413 			return 0;
1414 		}
1415 		pkt->fp_iov[i++].iov_len = len;
1416 		count += len;
1417 	}
1418 	pkt->fp_uio.uio_iovcnt = i;
1419 	pkt->fp_uio.uio_resid = count;
1420 
1421 	/* get trailer */
1422 	len = fwohci_buf_pktget(sc, &fb, (caddr_t *)&pkt->fp_trail,
1423 	    sizeof(*pkt->fp_trail));
1424 	if (len <= 0) {
1425 		printf("fwohci_buf_input: malformed input 3: %d\n",
1426 		    pkt->fp_hlen - count);
1427 		return 0;
1428 	}
1429 	return 1;
1430 }
1431 
1432 static int
1433 fwohci_buf_input_ppb(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1434     struct fwohci_pkt *pkt)
1435 {
1436 	caddr_t p;
1437 	int len;
1438 	struct fwohci_buf *fb;
1439 	struct fwohci_desc *fd;
1440 
1441 	if (fc->fc_type ==  FWOHCI_CTX_ISO_MULTI) {
1442 		return fwohci_buf_input(sc, fc, pkt);
1443 	}
1444 
1445 	memset(pkt, 0, sizeof(*pkt));
1446 	pkt->fp_uio.uio_iov = pkt->fp_iov;
1447 	pkt->fp_uio.uio_rw = UIO_WRITE;
1448 	pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
1449 
1450 	for (fb = TAILQ_FIRST(&fc->fc_buf); ; fb = TAILQ_NEXT(fb, fb_list)) {
1451 		if (fb == NULL)
1452 			return 0;
1453 		if (fb->fb_off == 0)
1454 			break;
1455 	}
1456 	fd = fb->fb_desc;
1457 	len = fd->fd_reqcount - fd->fd_rescount;
1458 	if (len == 0)
1459 		return 0;
1460 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
1461 	    BUS_DMASYNC_POSTREAD);
1462 
1463 	p = fb->fb_buf;
1464 	fb->fb_off += roundup(len, 4);
1465 	if (len < 8) {
1466 		printf("fwohci_buf_input_ppb: malformed input 1: %d\n", len);
1467 		return 0;
1468 	}
1469 
1470 	/*
1471 	 * get trailer first, may be bogus data unless status update
1472 	 * in descriptor is set.
1473 	 */
1474 	pkt->fp_trail = (u_int32_t *)p;
1475 	*pkt->fp_trail = (*pkt->fp_trail & 0xffff) | (fd->fd_status << 16);
1476 	pkt->fp_hdr[0] = ((u_int32_t *)p)[1];
1477 	pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
1478 #ifdef DIAGNOSTIC
1479 	if (pkt->fp_tcode != IEEE1394_TCODE_STREAM_DATA) {
1480 		printf("fwohci_buf_input_ppb: bad tcode: 0x%x\n",
1481 		    pkt->fp_tcode);
1482 		return 0;
1483 	}
1484 #endif
1485 	pkt->fp_hlen = 4;
1486 	pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
1487 	p += 8;
1488 	len -= 8;
1489 	if (pkt->fp_dlen != len) {
1490 		printf("fwohci_buf_input_ppb: malformed input 2: %d != %d\n",
1491 		    pkt->fp_dlen, len);
1492 		return 0;
1493 	}
1494 	DPRINTFN(1, ("fwohci_buf_input_ppb: tcode=0x%x, hlen=%d, dlen=%d\n",
1495 	    pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
1496 	pkt->fp_iov[0].iov_base = p;
1497 	pkt->fp_iov[0].iov_len = len;
1498 	pkt->fp_uio.uio_iovcnt = 0;
1499 	pkt->fp_uio.uio_resid = len;
1500 	return 1;
1501 }
1502 
1503 static int
1504 fwohci_handler_set(struct fwohci_softc *sc,
1505     int tcode, u_int32_t key1, u_int32_t key2,
1506     int (*handler)(struct fwohci_softc *, void *, struct fwohci_pkt *),
1507     void *arg)
1508 {
1509 	struct fwohci_ctx *fc;
1510 	struct fwohci_handler *fh;
1511 	int i, j;
1512 
1513 	if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1514 		int isasync = key1 & OHCI_ASYNC_STREAM;
1515 
1516 		key1 &= IEEE1394_ISOCH_MASK;
1517 		j = sc->sc_isoctx;
1518 		fh = NULL;
1519 		for (i = 0; i < sc->sc_isoctx; i++) {
1520 			if ((fc = sc->sc_ctx_ir[i]) == NULL) {
1521 				if (j == sc->sc_isoctx)
1522 					j = i;
1523 				continue;
1524 			}
1525 			fh = LIST_FIRST(&fc->fc_handler);
1526 			if (fh->fh_tcode == tcode &&
1527 			    fh->fh_key1 == key1 && fh->fh_key2 == key2)
1528 				break;
1529 			fh = NULL;
1530 		}
1531 		if (fh == NULL) {
1532 			if (handler == NULL)
1533 				return 0;
1534 			if (j == sc->sc_isoctx) {
1535 				DPRINTF(("fwohci_handler_set: no more free "
1536 				    "context\n"));
1537 				return ENOMEM;
1538 			}
1539 			if ((fc = sc->sc_ctx_ir[j]) == NULL) {
1540 				fwohci_ctx_alloc(sc, &fc, OHCI_BUF_IR_CNT, j,
1541 				    isasync ? FWOHCI_CTX_ISO_SINGLE :
1542 				    FWOHCI_CTX_ISO_MULTI);
1543 				sc->sc_ctx_ir[j] = fc;
1544 			}
1545 		}
1546 	} else {
1547 		switch (tcode) {
1548 		case IEEE1394_TCODE_WRITE_REQ_QUAD:
1549 		case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1550 		case IEEE1394_TCODE_READ_REQ_QUAD:
1551 		case IEEE1394_TCODE_READ_REQ_BLOCK:
1552 		case IEEE1394_TCODE_LOCK_REQ:
1553 			fc = sc->sc_ctx_arrq;
1554 			break;
1555 		case IEEE1394_TCODE_WRITE_RESP:
1556 		case IEEE1394_TCODE_READ_RESP_QUAD:
1557 		case IEEE1394_TCODE_READ_RESP_BLOCK:
1558 		case IEEE1394_TCODE_LOCK_RESP:
1559 			fc = sc->sc_ctx_arrs;
1560 			break;
1561 		default:
1562 			return EIO;
1563 		}
1564 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1565 		    fh = LIST_NEXT(fh, fh_list)) {
1566 			if (fh->fh_tcode == tcode &&
1567 			    fh->fh_key1 == key1 && fh->fh_key2 == key2)
1568 				break;
1569 		}
1570 	}
1571 	if (handler == NULL) {
1572 		if (fh != NULL) {
1573 			LIST_REMOVE(fh, fh_list);
1574 			free(fh, M_DEVBUF);
1575 		}
1576 		if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1577 			OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1578 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1579 			sc->sc_ctx_ir[fc->fc_ctx] = NULL;
1580 			fwohci_ctx_free(sc, fc);
1581 		}
1582 		return 0;
1583 	}
1584 	if (fh == NULL) {
1585 		fh = malloc(sizeof(*fh), M_DEVBUF, M_WAITOK);
1586 		LIST_INSERT_HEAD(&fc->fc_handler, fh, fh_list);
1587 	}
1588 	fh->fh_tcode = tcode;
1589 	fh->fh_key1 = key1;
1590 	fh->fh_key2 = key2;
1591 	fh->fh_handler = handler;
1592 	fh->fh_handarg = arg;
1593 	DPRINTFN(1, ("fwohci_handler_set: ctx %d, tcode %x, key 0x%x, 0x%x\n",
1594 	    fc->fc_ctx, tcode, key1, key2));
1595 
1596 	if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1597 		fwohci_ctx_init(sc, fc);
1598 		DPRINTFN(1, ("fwohci_handler_set: SYNC desc %ld\n",
1599 		    (long)(TAILQ_FIRST(&fc->fc_buf)->fb_desc - sc->sc_desc)));
1600 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1601 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1602 	}
1603 	return 0;
1604 }
1605 
1606 /*
1607  * Asyncronous Receive Requests input frontend.
1608  */
1609 static void
1610 fwohci_arrq_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1611 {
1612 	int rcode;
1613 	u_int32_t key1, key2;
1614 	struct fwohci_handler *fh;
1615 	struct fwohci_pkt pkt, res;
1616 
1617 	/*
1618 	 * Do not return if next packet is in the buffer, or the next
1619 	 * packet cannot be received until the next receive interrupt.
1620 	 */
1621 	while (fwohci_buf_input(sc, fc, &pkt)) {
1622 		if (pkt.fp_tcode == OHCI_TCODE_PHY) {
1623 			fwohci_phy_input(sc, &pkt);
1624 			continue;
1625 		}
1626 		key1 = pkt.fp_hdr[1] & 0xffff;
1627 		key2 = pkt.fp_hdr[2];
1628 		memset(&res, 0, sizeof(res));
1629 		res.fp_uio.uio_rw = UIO_WRITE;
1630 		res.fp_uio.uio_segflg = UIO_SYSSPACE;
1631 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1632 		    fh = LIST_NEXT(fh, fh_list)) {
1633 			if (pkt.fp_tcode == fh->fh_tcode &&
1634 			    key1 == fh->fh_key1 &&
1635 			    key2 == fh->fh_key2) {
1636 				rcode = (*fh->fh_handler)(sc, fh->fh_handarg,
1637 				    &pkt);
1638 				break;
1639 			}
1640 		}
1641 		if (fh == NULL) {
1642 			rcode = IEEE1394_RCODE_ADDRESS_ERROR;
1643 			DPRINTFN(1, ("fwohci_arrq_input: no listener: tcode "
1644 			    "0x%x, addr=0x%04x %08x\n", pkt.fp_tcode, key1,
1645 			    key2));
1646 		}
1647 		if (((*pkt.fp_trail & 0x001f0000) >> 16) !=
1648 		    OHCI_CTXCTL_EVENT_ACK_PENDING)
1649 			continue;
1650 		if (rcode != -1)
1651 			fwohci_atrs_output(sc, rcode, &pkt, &res);
1652 	}
1653 	fwohci_buf_next(sc, fc);
1654 	OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1655 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1656 }
1657 
1658 
1659 /*
1660  * Asynchronous Receive Response input frontend.
1661  */
1662 static void
1663 fwohci_arrs_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1664 {
1665 	struct fwohci_pkt pkt;
1666 	struct fwohci_handler *fh;
1667 	u_int16_t srcid;
1668 	int rcode, tlabel;
1669 
1670 	while (fwohci_buf_input(sc, fc, &pkt)) {
1671 		srcid = pkt.fp_hdr[1] >> 16;
1672 		rcode = (pkt.fp_hdr[1] & 0x0000f000) >> 12;
1673 		tlabel = (pkt.fp_hdr[0] & 0x0000fc00) >> 10;
1674 		DPRINTFN(1, ("fwohci_arrs_input: tcode 0x%x, from 0x%04x,"
1675 		    " tlabel 0x%x, rcode 0x%x, hlen %d, dlen %d\n",
1676 		    pkt.fp_tcode, srcid, tlabel, rcode, pkt.fp_hlen,
1677 		    pkt.fp_dlen));
1678 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1679 		    fh = LIST_NEXT(fh, fh_list)) {
1680 			if (pkt.fp_tcode == fh->fh_tcode &&
1681 			    (srcid & OHCI_NodeId_NodeNumber) == fh->fh_key1 &&
1682 			    tlabel == fh->fh_key2) {
1683 				(*fh->fh_handler)(sc, fh->fh_handarg, &pkt);
1684 				LIST_REMOVE(fh, fh_list);
1685 				free(fh, M_DEVBUF);
1686 				break;
1687 			}
1688 		}
1689 		if (fh == NULL)
1690 			DPRINTFN(1, ("fwohci_arrs_input: no listner\n"));
1691 	}
1692 	fwohci_buf_next(sc, fc);
1693 	OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1694 	    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1695 }
1696 
1697 /*
1698  * Isochronous Receive input frontend.
1699  */
1700 static void
1701 fwohci_ir_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1702 {
1703 	int rcode, chan, tag;
1704 	struct iovec *iov;
1705 	struct fwohci_handler *fh;
1706 	struct fwohci_pkt pkt;
1707 
1708 #if DOUBLEBUF
1709 	if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) {
1710 		struct fwohci_buf *fb;
1711 		int i;
1712 		u_int32_t reg;
1713 
1714 		/* stop dma engine before read buffer */
1715 		reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx,
1716 		    OHCI_SUBREG_ContextControlClear);
1717 		DPRINTFN(5, ("ir_input %08x =>", reg));
1718 		if (reg & OHCI_CTXCTL_RUN) {
1719 			OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1720 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1721 		}
1722 		DPRINTFN(5, (" %08x\n", OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlClear)));
1723 
1724 		i = 0;
1725 		while ((reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlSet)) & OHCI_CTXCTL_ACTIVE) {
1726 			delay(10);
1727 			if (++i > 10000) {
1728 				printf("cannot stop dma engine 0x08x\n", reg);
1729 				return;
1730 			}
1731 		}
1732 
1733 		/* rotate dma buffer */
1734 		fb = TAILQ_FIRST(&fc->fc_buf2);
1735 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_CommandPtr,
1736 		    fb->fb_daddr | 1);
1737 		/* start dma engine */
1738 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1739 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1740 		OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear,
1741 		    (1 << fc->fc_ctx));
1742 	}
1743 #endif
1744 
1745 	while (fwohci_buf_input_ppb(sc, fc, &pkt)) {
1746 		chan = (pkt.fp_hdr[0] & 0x00003f00) >> 8;
1747 		tag  = (pkt.fp_hdr[0] & 0x0000c000) >> 14;
1748 		DPRINTFN(1, ("fwohci_ir_input: hdr 0x%08x, tcode %d, hlen %d, "
1749 		    "dlen %d\n", pkt.fp_hdr[0], pkt.fp_tcode, pkt.fp_hlen,
1750 		    pkt.fp_dlen));
1751 		if (tag == IEEE1394_TAG_GASP) {
1752 			/*
1753 			 * The pkt with tag=3 is GASP format.
1754 			 * Move GASP header to header part.
1755 			 */
1756 			if (pkt.fp_dlen < 8)
1757 				continue;
1758 			iov = pkt.fp_iov;
1759 			/* assuming pkt per buffer mode */
1760 			pkt.fp_hdr[1] = ntohl(((u_int32_t *)iov->iov_base)[0]);
1761 			pkt.fp_hdr[2] = ntohl(((u_int32_t *)iov->iov_base)[1]);
1762 			iov->iov_base = (caddr_t)iov->iov_base + 8;
1763 			iov->iov_len -= 8;
1764 			pkt.fp_hlen += 8;
1765 			pkt.fp_dlen -= 8;
1766 		}
1767 		sc->sc_isopktcnt.ev_count++;
1768 		for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1769 		    fh = LIST_NEXT(fh, fh_list)) {
1770 			if (pkt.fp_tcode == fh->fh_tcode &&
1771 			    chan == fh->fh_key1 && tag == fh->fh_key2) {
1772 				rcode = (*fh->fh_handler)(sc, fh->fh_handarg,
1773 				    &pkt);
1774 				break;
1775 			}
1776 		}
1777 #ifdef FW_DEBUG
1778 		if (fh == NULL) {
1779 			DPRINTFN(1, ("fwohci_ir_input: no handler\n"));
1780 		} else {
1781 			DPRINTFN(1, ("fwohci_ir_input: rcode %d\n", rcode));
1782 		}
1783 #endif
1784 	}
1785 	fwohci_buf_next(sc, fc);
1786 
1787 	if (fc->fc_type == FWOHCI_CTX_ISO_SINGLE) {
1788 		OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1789 		    OHCI_SUBREG_ContextControlSet,
1790 		    OHCI_CTXCTL_WAKE);
1791 	}
1792 }
1793 
1794 /*
1795  * Asynchronous Transmit common routine.
1796  */
1797 static int
1798 fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1799     struct fwohci_pkt *pkt)
1800 {
1801 	struct fwohci_buf *fb;
1802 	struct fwohci_desc *fd;
1803 	struct mbuf *m, *m0;
1804 	int i, ndesc, error, off, len;
1805 	u_int32_t val;
1806 #ifdef FW_DEBUG
1807 	struct iovec *iov;
1808 #endif
1809 
1810 	if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == IEEE1394_BCAST_PHY_ID)
1811 		/* We can't send anything during selfid duration */
1812 		return EAGAIN;
1813 
1814 #ifdef FW_DEBUG
1815 	DPRINTFN(1, ("fwohci_at_output: tcode 0x%x, hlen %d, dlen %d",
1816 	    pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
1817 	for (i = 0; i < pkt->fp_hlen/4; i++)
1818 		DPRINTFN(2, ("%s%08x", i?" ":"\n    ", pkt->fp_hdr[i]));
1819 	DPRINTFN(2, ("$"));
1820 	for (ndesc = 0, iov = pkt->fp_iov;
1821 	     ndesc < pkt->fp_uio.uio_iovcnt; ndesc++, iov++) {
1822 		for (i = 0; i < iov->iov_len; i++)
1823 			DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n    ",
1824 			    ((u_int8_t *)iov->iov_base)[i]));
1825 		DPRINTFN(2, ("$"));
1826 	}
1827 	DPRINTFN(1, ("\n"));
1828 #endif
1829 
1830 	if ((m = pkt->fp_m) != NULL) {
1831 		for (ndesc = 2; m != NULL; m = m->m_next)
1832 			ndesc++;
1833 		if (ndesc > OHCI_DESC_MAX) {
1834 			m0 = NULL;
1835 			ndesc = 2;
1836 			for (off = 0; off < pkt->fp_dlen; off += len) {
1837 				if (m0 == NULL) {
1838 					MGETHDR(m0, M_DONTWAIT, MT_DATA);
1839 					if (m0 != NULL)
1840 						M_COPY_PKTHDR(m0, pkt->fp_m);
1841 					m = m0;
1842 				} else {
1843 					MGET(m->m_next, M_DONTWAIT, MT_DATA);
1844 					m = m->m_next;
1845 				}
1846 				if (m != NULL)
1847 					MCLGET(m, M_DONTWAIT);
1848 				if (m == NULL || (m->m_flags & M_EXT) == 0) {
1849 					m_freem(m0);
1850 					return ENOMEM;
1851 				}
1852 				len = pkt->fp_dlen - off;
1853 				if (len > m->m_ext.ext_size)
1854 					len = m->m_ext.ext_size;
1855 				m_copydata(pkt->fp_m, off, len,
1856 				    mtod(m, caddr_t));
1857 				m->m_len = len;
1858 				ndesc++;
1859 			}
1860 			m_freem(pkt->fp_m);
1861 			pkt->fp_m = m0;
1862 		}
1863 	} else
1864 		ndesc = 2 + pkt->fp_uio.uio_iovcnt;
1865 
1866 	if (ndesc > OHCI_DESC_MAX)
1867 		return ENOBUFS;
1868 
1869 	if (fc->fc_bufcnt > 50)			/*XXX*/
1870 		return ENOBUFS;
1871 	fb = malloc(sizeof(*fb), M_DEVBUF, M_WAITOK);
1872 	fb->fb_nseg = ndesc;
1873 	fb->fb_desc = fwohci_desc_get(sc, ndesc);
1874 	if (fb->fb_desc == NULL) {
1875 		free(fb, M_DEVBUF);
1876 		return ENOBUFS;
1877 	}
1878 	fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
1879 	    ((caddr_t)fb->fb_desc - (caddr_t)sc->sc_desc);
1880 	fb->fb_m = pkt->fp_m;
1881 	fb->fb_callback = pkt->fp_callback;
1882 	fb->fb_statuscb = pkt->fp_statuscb;
1883 	fb->fb_statusarg = pkt->fp_statusarg;
1884 
1885 	if (ndesc > 2) {
1886 		if ((error = bus_dmamap_create(sc->sc_dmat, pkt->fp_dlen, ndesc,
1887 		    PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) {
1888 			fwohci_desc_put(sc, fb->fb_desc, ndesc);
1889 			free(fb, M_DEVBUF);
1890 			return error;
1891 		}
1892 
1893 		if (pkt->fp_m != NULL)
1894 			error = bus_dmamap_load_mbuf(sc->sc_dmat, fb->fb_dmamap,
1895 			    pkt->fp_m, BUS_DMA_WAITOK);
1896 		else
1897 			error = bus_dmamap_load_uio(sc->sc_dmat, fb->fb_dmamap,
1898 			    &pkt->fp_uio, BUS_DMA_WAITOK);
1899 		if (error != 0) {
1900 			bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1901 			fwohci_desc_put(sc, fb->fb_desc, ndesc);
1902 			free(fb, M_DEVBUF);
1903 			return error;
1904 		}
1905 		bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, pkt->fp_dlen,
1906 		    BUS_DMASYNC_PREWRITE);
1907 	}
1908 
1909 	fd = fb->fb_desc;
1910 	fd->fd_flags = OHCI_DESC_IMMED;
1911 	fd->fd_reqcount = pkt->fp_hlen;
1912 	fd->fd_data = 0;
1913 	fd->fd_branch = 0;
1914 	fd->fd_status = 0;
1915 	if (fc->fc_ctx == OHCI_CTX_ASYNC_TX_RESPONSE) {
1916 		i = 3;				/* XXX: 3 sec */
1917 		val = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
1918 		fd->fd_timestamp = ((val >> 12) & 0x1fff) |
1919 		    ((((val >> 25) + i) & 0x7) << 13);
1920 	} else
1921 		fd->fd_timestamp = 0;
1922 	memcpy(fd + 1, pkt->fp_hdr, pkt->fp_hlen);
1923 	for (i = 0; i < ndesc - 2; i++) {
1924 		fd = fb->fb_desc + 2 + i;
1925 		fd->fd_flags = 0;
1926 		fd->fd_reqcount = fb->fb_dmamap->dm_segs[i].ds_len;
1927 		fd->fd_data = fb->fb_dmamap->dm_segs[i].ds_addr;
1928 		fd->fd_branch = 0;
1929 		fd->fd_status = 0;
1930 		fd->fd_timestamp = 0;
1931 	}
1932 	fd->fd_flags |= OHCI_DESC_LAST | OHCI_DESC_BRANCH;
1933 	fd->fd_flags |= OHCI_DESC_INTR_ALWAYS;
1934 
1935 #ifdef FW_DEBUG
1936 	DPRINTFN(1, ("fwohci_at_output: desc %ld",
1937 	    (long)(fb->fb_desc - sc->sc_desc)));
1938 	for (i = 0; i < ndesc * 4; i++)
1939 		DPRINTFN(2, ("%s%08x", i&7?" ":"\n    ",
1940 		    ((u_int32_t *)fb->fb_desc)[i]));
1941 	DPRINTFN(1, ("\n"));
1942 #endif
1943 
1944 	val = OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
1945 	    OHCI_SUBREG_ContextControlClear);
1946 
1947 	if (val & OHCI_CTXCTL_RUN) {
1948 		if (fc->fc_branch == NULL) {
1949 			OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1950 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1951 			goto run;
1952 		}
1953 		*fc->fc_branch = fb->fb_daddr | ndesc;
1954 		OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1955 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1956 	} else {
1957   run:
1958 		OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1959 		    OHCI_SUBREG_CommandPtr, fb->fb_daddr | ndesc);
1960 		OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1961 		    OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1962 	}
1963 	fc->fc_branch = &fd->fd_branch;
1964 
1965 	fc->fc_bufcnt++;
1966 	TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
1967 	pkt->fp_m = NULL;
1968 	return 0;
1969 }
1970 
1971 static void
1972 fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int force)
1973 {
1974 	struct fwohci_buf *fb;
1975 	struct fwohci_desc *fd;
1976 	struct fwohci_pkt pkt;
1977 	int i;
1978 
1979 	while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1980 		fd = fb->fb_desc;
1981 #ifdef FW_DEBUG
1982 		DPRINTFN(1, ("fwohci_at_done: %sdesc %ld (%d)",
1983 		    force ? "force " : "", (long)(fd - sc->sc_desc),
1984 		    fb->fb_nseg));
1985 		for (i = 0; i < fb->fb_nseg * 4; i++)
1986 			DPRINTFN(2, ("%s%08x", i&7?" ":"\n    ",
1987 			    ((u_int32_t *)fd)[i]));
1988 		DPRINTFN(1, ("\n"));
1989 #endif
1990 		if (fb->fb_nseg > 2)
1991 			fd += fb->fb_nseg - 1;
1992 		if (!force && !(fd->fd_status & OHCI_CTXCTL_ACTIVE))
1993 			break;
1994 		TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
1995 		if (fc->fc_branch == &fd->fd_branch) {
1996 			OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1997 			    OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1998 			fc->fc_branch = NULL;
1999 			for (i = 0; i < OHCI_LOOP; i++) {
2000 				if (!(OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
2001 				    OHCI_SUBREG_ContextControlClear) &
2002 				    OHCI_CTXCTL_ACTIVE))
2003 					break;
2004 				DELAY(10);
2005 			}
2006 		}
2007 
2008 		if (fb->fb_statuscb) {
2009 			memset(&pkt, 0, sizeof(pkt));
2010 			pkt.fp_status = fd->fd_status;
2011 			memcpy(pkt.fp_hdr, fd + 1, sizeof(pkt.fp_hdr[0]));
2012 
2013 			/* Indicate this is just returning the status bits. */
2014 			pkt.fp_tcode = -1;
2015 			(*fb->fb_statuscb)(sc, fb->fb_statusarg, &pkt);
2016 			fb->fb_statuscb = NULL;
2017 			fb->fb_statusarg = NULL;
2018 		}
2019 		fwohci_desc_put(sc, fb->fb_desc, fb->fb_nseg);
2020 		if (fb->fb_nseg > 2)
2021 			bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
2022 		fc->fc_bufcnt--;
2023 		if (fb->fb_callback) {
2024 			(*fb->fb_callback)(sc->sc_sc1394.sc1394_if, fb->fb_m);
2025 			fb->fb_callback = NULL;
2026 		} else if (fb->fb_m != NULL)
2027 			m_freem(fb->fb_m);
2028 		free(fb, M_DEVBUF);
2029 	}
2030 }
2031 
2032 /*
2033  * Asynchronous Transmit Reponse -- in response of request packet.
2034  */
2035 static void
2036 fwohci_atrs_output(struct fwohci_softc *sc, int rcode, struct fwohci_pkt *req,
2037     struct fwohci_pkt *res)
2038 {
2039 
2040 	if (((*req->fp_trail & 0x001f0000) >> 16) !=
2041 	    OHCI_CTXCTL_EVENT_ACK_PENDING)
2042 		return;
2043 
2044 	res->fp_hdr[0] = (req->fp_hdr[0] & 0x0000fc00) | 0x00000100;
2045 	res->fp_hdr[1] = (req->fp_hdr[1] & 0xffff0000) | (rcode << 12);
2046 	switch (req->fp_tcode) {
2047 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
2048 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
2049 		res->fp_tcode = IEEE1394_TCODE_WRITE_RESP;
2050 		res->fp_hlen = 12;
2051 		break;
2052 	case IEEE1394_TCODE_READ_REQ_QUAD:
2053 		res->fp_tcode = IEEE1394_TCODE_READ_RESP_QUAD;
2054 		res->fp_hlen = 16;
2055 		res->fp_dlen = 0;
2056 		if (res->fp_uio.uio_iovcnt == 1 && res->fp_iov[0].iov_len == 4)
2057 			res->fp_hdr[3] =
2058 			    *(u_int32_t *)res->fp_iov[0].iov_base;
2059 		res->fp_uio.uio_iovcnt = 0;
2060 		break;
2061 	case IEEE1394_TCODE_READ_REQ_BLOCK:
2062 	case IEEE1394_TCODE_LOCK_REQ:
2063 		if (req->fp_tcode == IEEE1394_TCODE_LOCK_REQ)
2064 			res->fp_tcode = IEEE1394_TCODE_LOCK_RESP;
2065 		else
2066 			res->fp_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
2067 		res->fp_hlen = 16;
2068 		res->fp_dlen = res->fp_uio.uio_resid;
2069 		res->fp_hdr[3] = res->fp_dlen << 16;
2070 		break;
2071 	}
2072 	res->fp_hdr[0] |= (res->fp_tcode << 4);
2073 	fwohci_at_output(sc, sc->sc_ctx_atrs, res);
2074 }
2075 
2076 /*
2077  * APPLICATION LAYER SERVICES
2078  */
2079 
2080 /*
2081  * Retrieve Global UID from GUID ROM
2082  */
2083 static int
2084 fwohci_guidrom_init(struct fwohci_softc *sc)
2085 {
2086 	int i, n, off;
2087 	u_int32_t val1, val2;
2088 
2089 	/* Extract the Global UID
2090 	 */
2091 	val1 = OHCI_CSR_READ(sc, OHCI_REG_GUIDHi);
2092 	val2 = OHCI_CSR_READ(sc, OHCI_REG_GUIDLo);
2093 
2094 	if (val1 != 0 || val2 != 0) {
2095 		sc->sc_sc1394.sc1394_guid[0] = (val1 >> 24) & 0xff;
2096 		sc->sc_sc1394.sc1394_guid[1] = (val1 >> 16) & 0xff;
2097 		sc->sc_sc1394.sc1394_guid[2] = (val1 >>  8) & 0xff;
2098 		sc->sc_sc1394.sc1394_guid[3] = (val1 >>  0) & 0xff;
2099 		sc->sc_sc1394.sc1394_guid[4] = (val2 >> 24) & 0xff;
2100 		sc->sc_sc1394.sc1394_guid[5] = (val2 >> 16) & 0xff;
2101 		sc->sc_sc1394.sc1394_guid[6] = (val2 >>  8) & 0xff;
2102 		sc->sc_sc1394.sc1394_guid[7] = (val2 >>  0) & 0xff;
2103 	} else {
2104 		val1 = OHCI_CSR_READ(sc, OHCI_REG_Version);
2105 		if ((val1 & OHCI_Version_GUID_ROM) == 0)
2106 			return -1;
2107 		OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom, OHCI_Guid_AddrReset);
2108 		for (i = 0; i < OHCI_LOOP; i++) {
2109 			val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
2110 			if (!(val1 & OHCI_Guid_AddrReset))
2111 				break;
2112 			DELAY(10);
2113 		}
2114 		off = OHCI_BITVAL(val1, OHCI_Guid_MiniROM) + 4;
2115 		val2 = 0;
2116 		for (n = 0; n < off + sizeof(sc->sc_sc1394.sc1394_guid); n++) {
2117 			OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom,
2118 			    OHCI_Guid_RdStart);
2119 			for (i = 0; i < OHCI_LOOP; i++) {
2120 				val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
2121 				if (!(val1 & OHCI_Guid_RdStart))
2122 					break;
2123 				DELAY(10);
2124 			}
2125 			if (n < off)
2126 				continue;
2127 			val1 = OHCI_BITVAL(val1, OHCI_Guid_RdData);
2128 			sc->sc_sc1394.sc1394_guid[n - off] = val1;
2129 			val2 |= val1;
2130 		}
2131 		if (val2 == 0)
2132 			return -1;
2133 	}
2134 	return 0;
2135 }
2136 
2137 /*
2138  * Initialization for Configuration ROM (no DMA context)
2139  */
2140 
2141 #define	CFR_MAXUNIT		20
2142 
2143 struct configromctx {
2144 	u_int32_t	*ptr;
2145 	int		curunit;
2146 	struct {
2147 		u_int32_t	*start;
2148 		int		length;
2149 		u_int32_t	*refer;
2150 		int		refunit;
2151 	} unit[CFR_MAXUNIT];
2152 };
2153 
2154 #define	CFR_PUT_DATA4(cfr, d1, d2, d3, d4)				\
2155 	(*(cfr)->ptr++ = (((d1)<<24) | ((d2)<<16) | ((d3)<<8) | (d4)))
2156 
2157 #define	CFR_PUT_DATA1(cfr, d)	(*(cfr)->ptr++ = (d))
2158 
2159 #define	CFR_PUT_VALUE(cfr, key, d)	(*(cfr)->ptr++ = ((key)<<24) | (d))
2160 
2161 #define	CFR_PUT_CRC(cfr, n)						\
2162 	(*(cfr)->unit[n].start = ((cfr)->unit[n].length << 16) |	\
2163 	    fwohci_crc16((cfr)->unit[n].start + 1, (cfr)->unit[n].length))
2164 
2165 #define	CFR_START_UNIT(cfr, n)						\
2166 do {									\
2167 	if ((cfr)->unit[n].refer != NULL) {				\
2168 		*(cfr)->unit[n].refer |=				\
2169 		    (cfr)->ptr - (cfr)->unit[n].refer;			\
2170 		CFR_PUT_CRC(cfr, (cfr)->unit[n].refunit);		\
2171 	}								\
2172 	(cfr)->curunit = (n);						\
2173 	(cfr)->unit[n].start = (cfr)->ptr++;				\
2174 } while (0 /* CONSTCOND */)
2175 
2176 #define	CFR_PUT_REFER(cfr, key, n)					\
2177 do {									\
2178 	(cfr)->unit[n].refer = (cfr)->ptr;				\
2179 	(cfr)->unit[n].refunit = (cfr)->curunit;			\
2180 	*(cfr)->ptr++ = (key) << 24;					\
2181 } while (0 /* CONSTCOND */)
2182 
2183 #define	CFR_END_UNIT(cfr)						\
2184 do {									\
2185 	(cfr)->unit[(cfr)->curunit].length = (cfr)->ptr -		\
2186 	    ((cfr)->unit[(cfr)->curunit].start + 1);			\
2187 	CFR_PUT_CRC(cfr, (cfr)->curunit);				\
2188 } while (0 /* CONSTCOND */)
2189 
2190 static u_int16_t
2191 fwohci_crc16(u_int32_t *ptr, int len)
2192 {
2193 	int shift;
2194 	u_int32_t crc, sum, data;
2195 
2196 	crc = 0;
2197 	while (len-- > 0) {
2198 		data = *ptr++;
2199 		for (shift = 28; shift >= 0; shift -= 4) {
2200 			sum = ((crc >> 12) ^ (data >> shift)) & 0x000f;
2201 			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
2202 		}
2203 		crc &= 0xffff;
2204 	}
2205 	return crc;
2206 }
2207 
2208 static void
2209 fwohci_configrom_init(struct fwohci_softc *sc)
2210 {
2211 	int i, val;
2212 	struct fwohci_buf *fb;
2213 	u_int32_t *hdr;
2214 	struct configromctx cfr;
2215 
2216 	fb = &sc->sc_buf_cnfrom;
2217 	memset(&cfr, 0, sizeof(cfr));
2218 	cfr.ptr = hdr = (u_int32_t *)fb->fb_buf;
2219 
2220 	/* headers */
2221 	CFR_START_UNIT(&cfr, 0);
2222 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusId));
2223 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusOptions));
2224 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDHi));
2225 	CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDLo));
2226 	CFR_END_UNIT(&cfr);
2227 	/* copy info_length from crc_length */
2228 	*hdr |= (*hdr & 0x00ff0000) << 8;
2229 	OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMhdr, *hdr);
2230 
2231 	/* root directory */
2232 	CFR_START_UNIT(&cfr, 1);
2233 	CFR_PUT_VALUE(&cfr, 0x03, 0x00005e);	/* vendor id */
2234 	CFR_PUT_REFER(&cfr, 0x81, 2);		/* textual descriptor offset */
2235 	CFR_PUT_VALUE(&cfr, 0x0c, 0x0083c0);	/* node capability */
2236 						/* spt,64,fix,lst,drq */
2237 #ifdef INET
2238 	CFR_PUT_REFER(&cfr, 0xd1, 3);		/* IPv4 unit directory */
2239 #endif /* INET */
2240 #ifdef INET6
2241 	CFR_PUT_REFER(&cfr, 0xd1, 4);		/* IPv6 unit directory */
2242 #endif /* INET6 */
2243 	CFR_END_UNIT(&cfr);
2244 
2245 	CFR_START_UNIT(&cfr, 2);
2246 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
2247 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
2248 	CFR_PUT_DATA4(&cfr, 'N', 'e', 't', 'B');
2249 	CFR_PUT_DATA4(&cfr, 'S', 'D', 0x00, 0x00);
2250 	CFR_END_UNIT(&cfr);
2251 
2252 #ifdef INET
2253 	/* IPv4 unit directory */
2254 	CFR_START_UNIT(&cfr, 3);
2255 	CFR_PUT_VALUE(&cfr, 0x12, 0x00005e);	/* unit spec id */
2256 	CFR_PUT_REFER(&cfr, 0x81, 6);		/* textual descriptor offset */
2257 	CFR_PUT_VALUE(&cfr, 0x13, 0x000001);	/* unit sw version */
2258 	CFR_PUT_REFER(&cfr, 0x81, 7);		/* textual descriptor offset */
2259 	CFR_END_UNIT(&cfr);
2260 
2261 	CFR_START_UNIT(&cfr, 6);
2262 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
2263 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
2264 	CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
2265 	CFR_END_UNIT(&cfr);
2266 
2267 	CFR_START_UNIT(&cfr, 7);
2268 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
2269 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
2270 	CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '4');
2271 	CFR_END_UNIT(&cfr);
2272 #endif /* INET */
2273 
2274 #ifdef INET6
2275 	/* IPv6 unit directory */
2276 	CFR_START_UNIT(&cfr, 4);
2277 	CFR_PUT_VALUE(&cfr, 0x12, 0x00005e);	/* unit spec id */
2278 	CFR_PUT_REFER(&cfr, 0x81, 8);		/* textual descriptor offset */
2279 	CFR_PUT_VALUE(&cfr, 0x13, 0x000002);	/* unit sw version */
2280 						/* XXX: TBA by IANA */
2281 	CFR_PUT_REFER(&cfr, 0x81, 9);		/* textual descriptor offset */
2282 	CFR_END_UNIT(&cfr);
2283 
2284 	CFR_START_UNIT(&cfr, 8);
2285 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
2286 	CFR_PUT_DATA1(&cfr, 0);			/* minimal ASCII */
2287 	CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
2288 	CFR_END_UNIT(&cfr);
2289 
2290 	CFR_START_UNIT(&cfr, 9);
2291 	CFR_PUT_VALUE(&cfr, 0, 0);		/* textual descriptor */
2292 	CFR_PUT_DATA1(&cfr, 0);
2293 	CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '6');
2294 	CFR_END_UNIT(&cfr);
2295 #endif /* INET6 */
2296 
2297 	fb->fb_off = cfr.ptr - hdr;
2298 #ifdef FW_DEBUG
2299 	DPRINTFN(2, ("%s: Config ROM:", sc->sc_sc1394.sc1394_dev.dv_xname));
2300 	for (i = 0; i < fb->fb_off; i++)
2301 		DPRINTFN(2, ("%s%08x", i&7?" ":"\n    ", hdr[i]));
2302 	DPRINTFN(2, ("\n"));
2303 #endif /* FW_DEBUG */
2304 
2305 	/*
2306 	 * Make network byte order for DMA
2307 	 */
2308 	for (i = 0; i < fb->fb_off; i++)
2309 		HTONL(hdr[i]);
2310 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
2311 	    (caddr_t)cfr.ptr - fb->fb_buf, BUS_DMASYNC_PREWRITE);
2312 
2313 	OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMmap,
2314 	    fb->fb_dmamap->dm_segs[0].ds_addr);
2315 
2316 	/* This register is only valid on OHCI 1.1. */
2317 	val = OHCI_CSR_READ(sc, OHCI_REG_Version);
2318 	if ((OHCI_Version_GET_Version(val) == 1) &&
2319 	    (OHCI_Version_GET_Revision(val) == 1))
2320 		OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet,
2321 		    OHCI_HCControl_BIBImageValid);
2322 
2323 	/* Just allow quad reads of the rom. */
2324 	for (i = 0; i < fb->fb_off; i++)
2325 		fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD,
2326 		    CSR_BASE_HI, CSR_BASE_LO + CSR_CONFIG_ROM + (i * 4),
2327 		    fwohci_configrom_input, NULL);
2328 }
2329 
2330 static int
2331 fwohci_configrom_input(struct fwohci_softc *sc, void *arg,
2332     struct fwohci_pkt *pkt)
2333 {
2334 	struct fwohci_pkt res;
2335 	u_int32_t loc, *rom;
2336 
2337 	/* This will be used as an array index so size accordingly. */
2338 	loc = pkt->fp_hdr[2] - (CSR_BASE_LO + CSR_CONFIG_ROM);
2339 	if ((loc & 0x03) != 0) {
2340 		/* alignment error */
2341 		return IEEE1394_RCODE_ADDRESS_ERROR;
2342 	}
2343 	else
2344 		loc /= 4;
2345 	rom = (u_int32_t *)sc->sc_buf_cnfrom.fb_buf;
2346 
2347 	DPRINTFN(1, ("fwohci_configrom_input: ConfigRom[0x%04x]: 0x%08x\n", loc,
2348 	    ntohl(rom[loc])));
2349 
2350 	memset(&res, 0, sizeof(res));
2351 	res.fp_hdr[3] = rom[loc];
2352 	fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res);
2353 	return -1;
2354 }
2355 
2356 /*
2357  * SelfID buffer (no DMA context)
2358  */
2359 static void
2360 fwohci_selfid_init(struct fwohci_softc *sc)
2361 {
2362 	struct fwohci_buf *fb;
2363 
2364 	fb = &sc->sc_buf_selfid;
2365 #ifdef DIAGNOSTIC
2366 	if ((fb->fb_dmamap->dm_segs[0].ds_addr & 0x7ff) != 0)
2367 		panic("fwohci_selfid_init: not aligned: %p (%ld) %p",
2368 		    (caddr_t)fb->fb_dmamap->dm_segs[0].ds_addr,
2369 		    (unsigned long)fb->fb_dmamap->dm_segs[0].ds_len, fb->fb_buf);
2370 #endif
2371 	memset(fb->fb_buf, 0, fb->fb_dmamap->dm_segs[0].ds_len);
2372 	bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
2373 	    fb->fb_dmamap->dm_segs[0].ds_len, BUS_DMASYNC_PREREAD);
2374 
2375 	OHCI_CSR_WRITE(sc, OHCI_REG_SelfIDBuffer,
2376 	    fb->fb_dmamap->dm_segs[0].ds_addr);
2377 }
2378 
2379 static int
2380 fwohci_selfid_input(struct fwohci_softc *sc)
2381 {
2382 	int i;
2383 	u_int32_t count, val, gen;
2384 	u_int32_t *buf;
2385 
2386 	buf = (u_int32_t *)sc->sc_buf_selfid.fb_buf;
2387 	val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
2388   again:
2389 	if (val & OHCI_SelfID_Error) {
2390 		printf("%s: SelfID Error\n", sc->sc_sc1394.sc1394_dev.dv_xname);
2391 		return -1;
2392 	}
2393 	count = OHCI_BITVAL(val, OHCI_SelfID_Size);
2394 
2395 	bus_dmamap_sync(sc->sc_dmat, sc->sc_buf_selfid.fb_dmamap,
2396 	    0, count << 2, BUS_DMASYNC_POSTREAD);
2397 	gen = OHCI_BITVAL(buf[0], OHCI_SelfID_Gen);
2398 
2399 #ifdef FW_DEBUG
2400 	DPRINTFN(1, ("%s: SelfID: 0x%08x", sc->sc_sc1394.sc1394_dev.dv_xname,
2401 	    val));
2402 	for (i = 0; i < count; i++)
2403 		DPRINTFN(2, ("%s%08x", i&7?" ":"\n    ", buf[i]));
2404 	DPRINTFN(1, ("\n"));
2405 #endif /* FW_DEBUG */
2406 
2407 	for (i = 1; i < count; i += 2) {
2408 		if (buf[i] != ~buf[i + 1])
2409 			break;
2410 		if (buf[i] & 0x00000001)
2411 			continue;	/* more pkt */
2412 		if (buf[i] & 0x00800000)
2413 			continue;	/* external id */
2414 		sc->sc_rootid = (buf[i] & 0x3f000000) >> 24;
2415 		if ((buf[i] & 0x00400800) == 0x00400800)
2416 			sc->sc_irmid = sc->sc_rootid;
2417 	}
2418 
2419 	val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
2420 	if (OHCI_BITVAL(val, OHCI_SelfID_Gen) != gen) {
2421 		if (OHCI_BITVAL(val, OHCI_SelfID_Gen) !=
2422 		    OHCI_BITVAL(buf[0], OHCI_SelfID_Gen))
2423 			goto again;
2424 		DPRINTF(("%s: SelfID Gen mismatch (%d, %d)\n",
2425 		    sc->sc_sc1394.sc1394_dev.dv_xname, gen,
2426 		    OHCI_BITVAL(val, OHCI_SelfID_Gen)));
2427 		return -1;
2428 	}
2429 	if (i != count) {
2430 		printf("%s: SelfID corrupted (%d, 0x%08x, 0x%08x)\n",
2431 		    sc->sc_sc1394.sc1394_dev.dv_xname, i, buf[i], buf[i + 1]);
2432 #if 1
2433 		if (i == 1 && buf[i] == 0 && buf[i + 1] == 0) {
2434 			/*
2435 			 * XXX: CXD3222 sometimes fails to DMA
2436 			 * selfid packet??
2437 			 */
2438 			sc->sc_rootid = (count - 1) / 2 - 1;
2439 			sc->sc_irmid = sc->sc_rootid;
2440 		} else
2441 #endif
2442 		return -1;
2443 	}
2444 
2445 	val = OHCI_CSR_READ(sc, OHCI_REG_NodeId);
2446 	if ((val & OHCI_NodeId_IDValid) == 0) {
2447 		sc->sc_nodeid = 0xffff;		/* invalid */
2448 		printf("%s: nodeid is invalid\n",
2449 		    sc->sc_sc1394.sc1394_dev.dv_xname);
2450 		return -1;
2451 	}
2452 	sc->sc_nodeid = val & 0xffff;
2453 
2454 	DPRINTF(("%s: nodeid=0x%04x(%d), rootid=%d, irmid=%d\n",
2455 	    sc->sc_sc1394.sc1394_dev.dv_xname, sc->sc_nodeid,
2456 	    sc->sc_nodeid & OHCI_NodeId_NodeNumber, sc->sc_rootid,
2457 	    sc->sc_irmid));
2458 
2459 	if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid)
2460 		return -1;
2461 
2462 	if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == sc->sc_rootid)
2463 		OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet,
2464 		    OHCI_LinkControl_CycleMaster);
2465 	else
2466 		OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear,
2467 		    OHCI_LinkControl_CycleMaster);
2468 	return 0;
2469 }
2470 
2471 /*
2472  * some CSRs are handled by driver.
2473  */
2474 static void
2475 fwohci_csr_init(struct fwohci_softc *sc)
2476 {
2477 	int i;
2478 	static u_int32_t csr[] = {
2479 	    CSR_STATE_CLEAR, CSR_STATE_SET, CSR_SB_CYCLE_TIME,
2480 	    CSR_SB_BUS_TIME, CSR_SB_BUSY_TIMEOUT, CSR_SB_BUS_MANAGER_ID,
2481 	    CSR_SB_CHANNEL_AVAILABLE_HI, CSR_SB_CHANNEL_AVAILABLE_LO,
2482 	    CSR_SB_BROADCAST_CHANNEL
2483 	};
2484 
2485 	for (i = 0; i < sizeof(csr) / sizeof(csr[0]); i++) {
2486 		fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_QUAD,
2487 		    CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL);
2488 		fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD,
2489 		    CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL);
2490 	}
2491 	sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] = 31;	/*XXX*/
2492 }
2493 
2494 static int
2495 fwohci_csr_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2496 {
2497 	struct fwohci_pkt res;
2498 	u_int32_t reg;
2499 
2500 	/*
2501 	 * XXX need to do special functionality other than just r/w...
2502 	 */
2503 	reg = pkt->fp_hdr[2] - CSR_BASE_LO;
2504 
2505 	if ((reg & 0x03) != 0) {
2506 		/* alignment error */
2507 		return IEEE1394_RCODE_ADDRESS_ERROR;
2508 	}
2509 	DPRINTFN(1, ("fwohci_csr_input: CSR[0x%04x]: 0x%08x", reg,
2510 	    *(u_int32_t *)(&sc->sc_csr[reg])));
2511 	if (pkt->fp_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) {
2512 		DPRINTFN(1, (" -> 0x%08x\n",
2513 		    ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base)));
2514 		*(u_int32_t *)&sc->sc_csr[reg] =
2515 		    ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base);
2516 	} else {
2517 		DPRINTFN(1, ("\n"));
2518 		res.fp_hdr[3] = htonl(*(u_int32_t *)&sc->sc_csr[reg]);
2519 		res.fp_iov[0].iov_base = &res.fp_hdr[3];
2520 		res.fp_iov[0].iov_len = 4;
2521 		res.fp_uio.uio_resid = 4;
2522 		res.fp_uio.uio_iovcnt = 1;
2523 		fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res);
2524 		return -1;
2525 	}
2526 	return IEEE1394_RCODE_COMPLETE;
2527 }
2528 
2529 /*
2530  * Mapping between nodeid and unique ID (EUI-64).
2531  *
2532  * Track old mappings and simply update their devices with the new id's when
2533  * they match an existing EUI. This allows proper renumeration of the bus.
2534  */
2535 static void
2536 fwohci_uid_collect(struct fwohci_softc *sc)
2537 {
2538 	int i;
2539 	struct fwohci_uidtbl *fu;
2540 	struct ieee1394_softc *iea;
2541 
2542 	LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node)
2543 		iea->sc1394_node_id = 0xffff;
2544 
2545 	if (sc->sc_uidtbl != NULL)
2546 		free(sc->sc_uidtbl, M_DEVBUF);
2547 	sc->sc_uidtbl = malloc(sizeof(*fu) * (sc->sc_rootid + 1), M_DEVBUF,
2548 	    M_NOWAIT);		/* XXX M_WAITOK requires locks */
2549 	if (sc->sc_uidtbl == NULL)
2550 		return;
2551 	memset(sc->sc_uidtbl, 0, sizeof(*fu) * (sc->sc_rootid + 1));
2552 
2553 	for (i = 0, fu = sc->sc_uidtbl; i <= sc->sc_rootid; i++, fu++) {
2554 		if (i == (sc->sc_nodeid & OHCI_NodeId_NodeNumber)) {
2555 			memcpy(fu->fu_uid, sc->sc_sc1394.sc1394_guid, 8);
2556 			fu->fu_valid = 3;
2557 
2558 			iea = (struct ieee1394_softc *)sc->sc_sc1394.sc1394_if;
2559 			if (iea) {
2560 				iea->sc1394_node_id = i;
2561 				DPRINTF(("%s: Updating nodeid to %d\n",
2562 				    iea->sc1394_dev.dv_xname,
2563 				    iea->sc1394_node_id));
2564 			}
2565 		} else {
2566 			fu->fu_valid = 0;
2567 			fwohci_uid_req(sc, i);
2568 		}
2569 	}
2570 	if (sc->sc_rootid == 0)
2571 		fwohci_check_nodes(sc);
2572 }
2573 
2574 static void
2575 fwohci_uid_req(struct fwohci_softc *sc, int phyid)
2576 {
2577 	struct fwohci_pkt pkt;
2578 
2579 	memset(&pkt, 0, sizeof(pkt));
2580 	pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
2581 	pkt.fp_hlen = 12;
2582 	pkt.fp_dlen = 0;
2583 	pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
2584 	    (pkt.fp_tcode << 4);
2585 	pkt.fp_hdr[1] = ((0xffc0 | phyid) << 16) | CSR_BASE_HI;
2586 	pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12;
2587 	fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
2588 	    sc->sc_tlabel, fwohci_uid_input, (void *)0);
2589 	sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
2590 	fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
2591 
2592 	pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
2593 	    (pkt.fp_tcode << 4);
2594 	pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16;
2595 	fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
2596 	    sc->sc_tlabel, fwohci_uid_input, (void *)1);
2597 	sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
2598 	fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
2599 }
2600 
2601 static int
2602 fwohci_uid_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *res)
2603 {
2604 	struct fwohci_uidtbl *fu;
2605 	struct ieee1394_softc *iea;
2606 	struct ieee1394_attach_args fwa;
2607 	int i, n, done, rcode, found;
2608 
2609 	found = 0;
2610 
2611 	n = (res->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2612 	rcode = (res->fp_hdr[1] & 0x0000f000) >> 12;
2613 	if (rcode != IEEE1394_RCODE_COMPLETE ||
2614 	    sc->sc_uidtbl == NULL ||
2615 	    n > sc->sc_rootid)
2616 		return 0;
2617 	fu = &sc->sc_uidtbl[n];
2618 	if (arg == 0) {
2619 		memcpy(fu->fu_uid, res->fp_iov[0].iov_base, 4);
2620 		fu->fu_valid |= 0x1;
2621 	} else {
2622 		memcpy(fu->fu_uid + 4, res->fp_iov[0].iov_base, 4);
2623 		fu->fu_valid |= 0x2;
2624 	}
2625 #ifdef FW_DEBUG
2626 	if (fu->fu_valid == 0x3)
2627 		DPRINTFN(1, ("fwohci_uid_input: "
2628 		    "Node %d, UID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", n,
2629 		    fu->fu_uid[0], fu->fu_uid[1], fu->fu_uid[2], fu->fu_uid[3],
2630 		    fu->fu_uid[4], fu->fu_uid[5], fu->fu_uid[6], fu->fu_uid[7]));
2631 #endif
2632 	if (fu->fu_valid == 0x3) {
2633 		LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node)
2634 			if (memcmp(iea->sc1394_guid, fu->fu_uid, 8) == 0) {
2635 				found = 1;
2636 				iea->sc1394_node_id = n;
2637 				DPRINTF(("%s: Updating nodeid to %d\n",
2638 				    iea->sc1394_dev.dv_xname,
2639 				    iea->sc1394_node_id));
2640 				break;
2641 			}
2642 		if (!found) {
2643 			strcpy(fwa.name, "fwnode");
2644 			memcpy(fwa.uid, fu->fu_uid, 8);
2645 			fwa.nodeid = n;
2646 			fwa.read = fwohci_read;
2647 			fwa.write = fwohci_write;
2648 			fwa.inreg = fwohci_inreg;
2649 			iea = (struct ieee1394_softc *)
2650 			    config_found_sm(&sc->sc_sc1394.sc1394_dev, &fwa,
2651 			    fwohci_print, fwohci_submatch);
2652 			if (iea != NULL)
2653 				LIST_INSERT_HEAD(&sc->sc_nodelist, iea,
2654 				    sc1394_node);
2655 		}
2656 	}
2657 	done = 1;
2658 
2659 	for (i = 0; i < sc->sc_rootid + 1; i++) {
2660 		fu = &sc->sc_uidtbl[i];
2661 		if (fu->fu_valid != 0x3) {
2662 			done = 0;
2663 			break;
2664 		}
2665 	}
2666 	if (done)
2667 		fwohci_check_nodes(sc);
2668 
2669 	return 0;
2670 }
2671 
2672 static void
2673 fwohci_check_nodes(struct fwohci_softc *sc)
2674 {
2675 	struct device *detach = NULL;
2676 	struct ieee1394_softc *iea;
2677 
2678 	LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) {
2679 
2680 		/*
2681 		 * Have to defer detachment until the next
2682 		 * loop iteration since config_detach
2683 		 * free's the softc and the loop iterator
2684 		 * needs data from the softc to move
2685 		 * forward.
2686 		 */
2687 
2688 		if (detach) {
2689 			config_detach(detach, 0);
2690 			detach = NULL;
2691 		}
2692 		if (iea->sc1394_node_id == 0xffff) {
2693 			detach = (struct device *)iea;
2694 			LIST_REMOVE(iea, sc1394_node);
2695 		}
2696 	}
2697 	if (detach)
2698 		config_detach(detach, 0);
2699 }
2700 
2701 static int
2702 fwohci_uid_lookup(struct fwohci_softc *sc, const u_int8_t *uid)
2703 {
2704 	struct fwohci_uidtbl *fu;
2705 	int n;
2706 	static const u_int8_t bcast[] =
2707 	    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2708 
2709 	fu = sc->sc_uidtbl;
2710 	if (fu == NULL) {
2711 		if (memcmp(uid, bcast, sizeof(bcast)) == 0)
2712 			return IEEE1394_BCAST_PHY_ID;
2713 		fwohci_uid_collect(sc); /* try to get */
2714 		return -1;
2715 	}
2716 	for (n = 0; n <= sc->sc_rootid; n++, fu++) {
2717 		if (fu->fu_valid == 0x3 && memcmp(fu->fu_uid, uid, 8) == 0)
2718 			return n;
2719 	}
2720 	if (memcmp(uid, bcast, sizeof(bcast)) == 0)
2721 		return IEEE1394_BCAST_PHY_ID;
2722 	for (n = 0, fu = sc->sc_uidtbl; n <= sc->sc_rootid; n++, fu++) {
2723 		if (fu->fu_valid != 0x3) {
2724 			/*
2725 			 * XXX: need timer before retransmission
2726 			 */
2727 			fwohci_uid_req(sc, n);
2728 		}
2729 	}
2730 	return -1;
2731 }
2732 
2733 /*
2734  * functions to support network interface
2735  */
2736 static int
2737 fwohci_if_inreg(struct device *self, u_int32_t offhi, u_int32_t offlo,
2738     void (*handler)(struct device *, struct mbuf *))
2739 {
2740 	struct fwohci_softc *sc = (struct fwohci_softc *)self;
2741 
2742 	fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_BLOCK, offhi, offlo,
2743 	    handler ? fwohci_if_input : NULL, handler);
2744 	fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA,
2745 	    (sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & IEEE1394_ISOCH_MASK) | OHCI_ASYNC_STREAM,
2746 	    IEEE1394_TAG_GASP, handler ? fwohci_if_input : NULL, handler);
2747 	return 0;
2748 }
2749 
2750 static int
2751 fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2752 {
2753 	int n, len;
2754 	struct mbuf *m;
2755 	struct iovec *iov;
2756 	void (*handler)(struct device *, struct mbuf *) = arg;
2757 
2758 #ifdef FW_DEBUG
2759 	int i;
2760 	DPRINTFN(1, ("fwohci_if_input: tcode=0x%x, dlen=%d", pkt->fp_tcode,
2761 	    pkt->fp_dlen));
2762 	for (i = 0; i < pkt->fp_hlen/4; i++)
2763 		DPRINTFN(2, ("%s%08x", i?" ":"\n    ", pkt->fp_hdr[i]));
2764 	DPRINTFN(2, ("$"));
2765 	for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
2766 		iov = &pkt->fp_iov[n];
2767 		for (i = 0; i < iov->iov_len; i++)
2768 			DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n    ",
2769 			    ((u_int8_t *)iov->iov_base)[i]));
2770 		DPRINTFN(2, ("$"));
2771 	}
2772 	DPRINTFN(1, ("\n"));
2773 #endif /* FW_DEBUG */
2774 	len = pkt->fp_dlen;
2775 	MGETHDR(m, M_DONTWAIT, MT_DATA);
2776 	if (m == NULL)
2777 		return IEEE1394_RCODE_COMPLETE;
2778 	m->m_len = 16;
2779 	if (len + m->m_len > MHLEN) {
2780 		MCLGET(m, M_DONTWAIT);
2781 		if ((m->m_flags & M_EXT) == 0) {
2782 			m_freem(m);
2783 			return IEEE1394_RCODE_COMPLETE;
2784 		}
2785 	}
2786 	n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2787 	if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
2788 	    sc->sc_uidtbl[n].fu_valid != 0x3) {
2789 		printf("%s: packet from unknown node: phy id %d\n",
2790 		    sc->sc_sc1394.sc1394_dev.dv_xname, n);
2791 		m_freem(m);
2792 		fwohci_uid_req(sc, n);
2793 		return IEEE1394_RCODE_COMPLETE;
2794 	}
2795 	memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
2796 	if (pkt->fp_tcode == IEEE1394_TCODE_STREAM_DATA) {
2797 		m->m_flags |= M_BCAST;
2798 		mtod(m, u_int32_t *)[2] = mtod(m, u_int32_t *)[3] = 0;
2799 	} else {
2800 		mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
2801 		mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
2802 	}
2803 	mtod(m, u_int8_t *)[8] = n;	/*XXX: node id for debug */
2804 	mtod(m, u_int8_t *)[9] =
2805 	    (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
2806 	    ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
2807 
2808 	m->m_pkthdr.rcvif = NULL;	/* set in child */
2809 	m->m_pkthdr.len = len + m->m_len;
2810 	/*
2811 	 * We may use receive buffer by external mbuf instead of copy here.
2812 	 * But asynchronous receive buffer must be operate in buffer fill
2813 	 * mode, so that each receive buffer will shared by multiple mbufs.
2814 	 * If upper layer doesn't free mbuf soon, e.g. application program
2815 	 * is suspended, buffer must be reallocated.
2816 	 * Isochronous buffer must be operate in packet buffer mode, and
2817 	 * it is easy to map receive buffer to external mbuf.  But it is
2818 	 * used for broadcast/multicast only, and is expected not so
2819 	 * performance sensitive for now.
2820 	 * XXX: The performance may be important for multicast case,
2821 	 * so we should revisit here later.
2822 	 *						-- onoe
2823 	 */
2824 	n = 0;
2825 	iov = pkt->fp_uio.uio_iov;
2826 	while (len > 0) {
2827 		memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
2828 		    iov->iov_len);
2829 		m->m_len += iov->iov_len;
2830 		len -= iov->iov_len;
2831 		iov++;
2832 	}
2833 	(*handler)(sc->sc_sc1394.sc1394_if, m);
2834 	return IEEE1394_RCODE_COMPLETE;
2835 }
2836 
2837 static int
2838 fwohci_if_input_iso(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2839 {
2840 	int n, len;
2841 	int chan, tag;
2842 	struct mbuf *m;
2843 	struct iovec *iov;
2844 	void (*handler)(struct device *, struct mbuf *) = arg;
2845 #ifdef FW_DEBUG
2846 	int i;
2847 #endif
2848 
2849 	chan = (pkt->fp_hdr[0] & 0x00003f00) >> 8;
2850 	tag  = (pkt->fp_hdr[0] & 0x0000c000) >> 14;
2851 #ifdef FW_DEBUG
2852 	DPRINTFN(1, ("fwohci_if_input_iso: "
2853 	    "tcode=0x%x, chan=%d, tag=%x, dlen=%d",
2854 	    pkt->fp_tcode, chan, tag, pkt->fp_dlen));
2855 	for (i = 0; i < pkt->fp_hlen/4; i++)
2856 		DPRINTFN(2, ("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i]));
2857 	DPRINTFN(2, ("$"));
2858 	for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
2859 		iov = &pkt->fp_iov[n];
2860 		for (i = 0; i < iov->iov_len; i++)
2861 			DPRINTFN(2, ("%s%02x",
2862 			    (i%32)?((i%4)?"":" "):"\n\t",
2863 			    ((u_int8_t *)iov->iov_base)[i]));
2864 		DPRINTFN(2, ("$"));
2865 	}
2866 	DPRINTFN(2, ("\n"));
2867 #endif /* FW_DEBUG */
2868 	len = pkt->fp_dlen;
2869 	MGETHDR(m, M_DONTWAIT, MT_DATA);
2870 	if (m == NULL)
2871 		return IEEE1394_RCODE_COMPLETE;
2872 	m->m_len = 16;
2873 	if (m->m_len + len > MHLEN) {
2874 		MCLGET(m, M_DONTWAIT);
2875 		if ((m->m_flags & M_EXT) == 0) {
2876 			m_freem(m);
2877 			return IEEE1394_RCODE_COMPLETE;
2878 		}
2879 	}
2880 
2881 	m->m_flags |= M_BCAST;
2882 
2883 	if (tag == IEEE1394_TAG_GASP) {
2884 		n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2885 		if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
2886 		    sc->sc_uidtbl[n].fu_valid != 0x3) {
2887 			printf("%s: packet from unknown node: phy id %d\n",
2888 			    sc->sc_sc1394.sc1394_dev.dv_xname, n);
2889 			m_freem(m);
2890 			return IEEE1394_RCODE_COMPLETE;
2891 		}
2892 		memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
2893 		mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
2894 		mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
2895 		mtod(m, u_int8_t *)[8] = n;	/*XXX: node id for debug */
2896 		mtod(m, u_int8_t *)[9] =
2897 		    (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
2898 		    ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
2899 	} else {
2900 		m->m_flags |= M_LINK0;
2901 	}
2902 	mtod(m, u_int8_t *)[14] = chan;
2903 	mtod(m, u_int8_t *)[15] = tag;
2904 
2905 
2906 	m->m_pkthdr.rcvif = NULL;	/* set in child */
2907 	m->m_pkthdr.len = len + m->m_len;
2908 	/*
2909 	 * We may use receive buffer by external mbuf instead of copy here.
2910 	 * But asynchronous receive buffer must be operate in buffer fill
2911 	 * mode, so that each receive buffer will shared by multiple mbufs.
2912 	 * If upper layer doesn't free mbuf soon, e.g. application program
2913 	 * is suspended, buffer must be reallocated.
2914 	 * Isochronous buffer must be operate in packet buffer mode, and
2915 	 * it is easy to map receive buffer to external mbuf.  But it is
2916 	 * used for broadcast/multicast only, and is expected not so
2917 	 * performance sensitive for now.
2918 	 * XXX: The performance may be important for multicast case,
2919 	 * so we should revisit here later.
2920 	 *						-- onoe
2921 	 */
2922 	n = 0;
2923 	iov = pkt->fp_uio.uio_iov;
2924 	while (len > 0) {
2925 		memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
2926 		    iov->iov_len);
2927 	        m->m_len += iov->iov_len;
2928 	        len -= iov->iov_len;
2929 		iov++;
2930 	}
2931 	(*handler)(sc->sc_sc1394.sc1394_if, m);
2932 	return IEEE1394_RCODE_COMPLETE;
2933 }
2934 
2935 
2936 
2937 static int
2938 fwohci_if_output(struct device *self, struct mbuf *m0,
2939     void (*callback)(struct device *, struct mbuf *))
2940 {
2941 	struct fwohci_softc *sc = (struct fwohci_softc *)self;
2942 	struct fwohci_pkt pkt;
2943 	u_int8_t *p;
2944 	int n, error, spd, hdrlen, maxrec;
2945 #ifdef FW_DEBUG
2946 	struct mbuf *m;
2947 #endif
2948 
2949 	p = mtod(m0, u_int8_t *);
2950 	if (m0->m_flags & (M_BCAST | M_MCAST)) {
2951 		spd = IEEE1394_SPD_S100;	/*XXX*/
2952 		maxrec = 512;			/*XXX*/
2953 		hdrlen = 8;
2954 	} else {
2955 		n = fwohci_uid_lookup(sc, p);
2956 		if (n < 0) {
2957 			printf("%s: nodeid unknown:"
2958 			    " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
2959 			    sc->sc_sc1394.sc1394_dev.dv_xname,
2960 			    p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
2961 			error = EHOSTUNREACH;
2962 			goto end;
2963 		}
2964 		if (n == IEEE1394_BCAST_PHY_ID) {
2965 			printf("%s: broadcast with !M_MCAST\n",
2966 			    sc->sc_sc1394.sc1394_dev.dv_xname);
2967 #ifdef FW_DEBUG
2968 			DPRINTFN(2, ("packet:"));
2969 			for (m = m0; m != NULL; m = m->m_next) {
2970 				for (n = 0; n < m->m_len; n++)
2971 					DPRINTFN(2, ("%s%02x", (n%32)?
2972 					    ((n%4)?"":" "):"\n    ",
2973 					    mtod(m, u_int8_t *)[n]));
2974 				DPRINTFN(2, ("$"));
2975 			}
2976 			DPRINTFN(2, ("\n"));
2977 #endif
2978 			error = EHOSTUNREACH;
2979 			goto end;
2980 		}
2981 		maxrec = 2 << p[8];
2982 		spd = p[9];
2983 		hdrlen = 0;
2984 	}
2985 	if (spd > sc->sc_sc1394.sc1394_link_speed) {
2986 		DPRINTF(("fwohci_if_output: spd (%d) is faster than %d\n",
2987 		    spd, sc->sc_sc1394.sc1394_link_speed));
2988 		spd = sc->sc_sc1394.sc1394_link_speed;
2989 	}
2990 	if (maxrec > (512 << spd)) {
2991 		DPRINTF(("fwohci_if_output: maxrec (%d) is larger for spd (%d)"
2992 		    "\n", maxrec, spd));
2993 		maxrec = 512 << spd;
2994 	}
2995 	while (maxrec > sc->sc_sc1394.sc1394_max_receive) {
2996 		DPRINTF(("fwohci_if_output: maxrec (%d) is larger than"
2997 		    " %d\n", maxrec, sc->sc_sc1394.sc1394_max_receive));
2998 		maxrec >>= 1;
2999 	}
3000 	if (maxrec < 512) {
3001 		DPRINTF(("fwohci_if_output: maxrec (%d) is smaller than "
3002 		    "minimum\n", maxrec));
3003 		maxrec = 512;
3004 	}
3005 
3006 	m_adj(m0, 16 - hdrlen);
3007 	if (m0->m_pkthdr.len > maxrec) {
3008 		DPRINTF(("fwohci_if_output: packet too big: hdr %d, pktlen "
3009 		    "%d, maxrec %d\n", hdrlen, m0->m_pkthdr.len, maxrec));
3010 		error = E2BIG;	/*XXX*/
3011 		goto end;
3012 	}
3013 
3014 	memset(&pkt, 0, sizeof(pkt));
3015 	pkt.fp_uio.uio_iov = pkt.fp_iov;
3016 	pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
3017 	pkt.fp_uio.uio_rw = UIO_WRITE;
3018 	if (m0->m_flags & (M_BCAST | M_MCAST)) {
3019 		/* construct GASP header */
3020 		p = mtod(m0, u_int8_t *);
3021 		p[0] = sc->sc_nodeid >> 8;
3022 		p[1] = sc->sc_nodeid & 0xff;
3023 		p[2] = 0x00; p[3] = 0x00; p[4] = 0x5e;
3024 		p[5] = 0x00; p[6] = 0x00; p[7] = 0x01;
3025 		pkt.fp_tcode = IEEE1394_TCODE_STREAM_DATA;
3026 		pkt.fp_hlen = 8;
3027 		pkt.fp_hdr[0] = (spd << 16) | (IEEE1394_TAG_GASP << 14) |
3028 		    ((sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] &
3029 		    OHCI_NodeId_NodeNumber) << 8);
3030 		pkt.fp_hdr[1] = m0->m_pkthdr.len << 16;
3031 	} else {
3032 		pkt.fp_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
3033 		pkt.fp_hlen = 16;
3034 		pkt.fp_hdr[0] = 0x00800100 | (sc->sc_tlabel << 10) |
3035 		    (spd << 16);
3036 		pkt.fp_hdr[1] =
3037 		    (((sc->sc_nodeid & OHCI_NodeId_BusNumber) | n) << 16) |
3038 		    (p[10] << 8) | p[11];
3039 		pkt.fp_hdr[2] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15];
3040 		pkt.fp_hdr[3] = m0->m_pkthdr.len << 16;
3041 		sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3042 	}
3043 	pkt.fp_hdr[0] |= (pkt.fp_tcode << 4);
3044 	pkt.fp_dlen = m0->m_pkthdr.len;
3045 	pkt.fp_m = m0;
3046 	pkt.fp_callback = callback;
3047 	error = fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
3048 	m0 = pkt.fp_m;
3049   end:
3050 	if (m0 != NULL) {
3051 		if (callback)
3052 			(*callback)(sc->sc_sc1394.sc1394_if, m0);
3053 		else
3054 			m_freem(m0);
3055 	}
3056 	return error;
3057 }
3058 
3059 /*
3060  * High level routines to provide abstraction to attaching layers to
3061  * send/receive data.
3062  */
3063 
3064 /*
3065  * These break down into 4 routines as follows:
3066  *
3067  * int fwohci_read(struct ieee1394_abuf *)
3068  *
3069  * This routine will attempt to read a region from the requested node.
3070  * A callback must be provided which will be called when either the completed
3071  * read is done or an unrecoverable error occurs. This is mainly a convenience
3072  * routine since it will encapsulate retrying a region as quadlet vs. block reads
3073  * and recombining all the returned data. This could also be done with a series
3074  * of write/inreg's for each packet sent.
3075  *
3076  * int fwohci_write(struct ieee1394_abuf *)
3077  *
3078  * The work horse main entry point for putting packets on the bus. This is the
3079  * generalized interface for fwnode/etc code to put packets out onto the bus.
3080  * It accepts all standard ieee1394 tcodes (XXX: only a few today) and optionally
3081  * will callback via a func pointer to the calling code with the resulting ACK
3082  * code from the packet. If the ACK code is to be ignored (i.e. no cb) then the
3083  * write routine will take care of free'ing the abuf since the fwnode/etc code
3084  * won't have any knowledge of when to do this. This allows for simple one-off
3085  * packets to be sent from the upper-level code without worrying about a callback
3086  * for cleanup.
3087  *
3088  * int fwohci_inreg(struct ieee1394_abuf *, int)
3089  *
3090  * This is very simple. It evals the abuf passed in and registers an internal
3091  * handler as the callback for packets received for that operation.
3092  * The integer argument specifies whether on a block read/write operation to
3093  * allow sub-regions to be read/written (in block form) as well.
3094  *
3095  * XXX: This whole structure needs to be redone as a list of regions and
3096  * operations allowed on those regions.
3097  *
3098  * int fwohci_unreg(struct ieee1394_abuf *, int)
3099  *
3100  * XXX: TBD. For now passing in a NULL ab_cb to inreg will unregister. This
3101  * routine will simply verify ab_cb is NULL and call inreg.
3102  *
3103  * This simply unregisters the respective callback done via inreg for items
3104  * which only need to register an area for a one-time operation (like a status
3105  * buffer a remote node will write to when the current operation is done). The
3106  * int argument specifies the same behavior as inreg, except in reverse (i.e.
3107  * it unregisters).
3108  */
3109 
3110 static int
3111 fwohci_read(struct ieee1394_abuf *ab)
3112 {
3113 	struct fwohci_pkt pkt;
3114 	struct ieee1394_softc *sc = ab->ab_req;
3115 	struct fwohci_softc *psc =
3116 	    (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3117 	struct fwohci_cb *fcb;
3118 	u_int32_t high, lo;
3119 	int rv, tcode;
3120 
3121 	/* Have to have a callback when reading. */
3122 	if (ab->ab_cb == NULL)
3123 		return -1;
3124 
3125 	fcb = malloc(sizeof(struct fwohci_cb), M_DEVBUF, M_WAITOK);
3126 	fcb->ab = ab;
3127 	fcb->count = 0;
3128 	fcb->abuf_valid = 1;
3129 
3130 	high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3131 	lo = (ab->ab_csr & 0x00000000ffffffff);
3132 
3133 	memset(&pkt, 0, sizeof(pkt));
3134 	pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3135 	pkt.fp_hdr[2] = lo;
3136 	pkt.fp_dlen = 0;
3137 
3138 	if (ab->ab_length == 4) {
3139 		pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3140 		tcode = IEEE1394_TCODE_READ_RESP_QUAD;
3141 		pkt.fp_hlen = 12;
3142 	} else {
3143 		pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
3144 		pkt.fp_hlen = 16;
3145 		tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
3146 		pkt.fp_hdr[3] = (ab->ab_length << 16);
3147 	}
3148 	pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3149 	    (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
3150 
3151 	pkt.fp_statusarg = fcb;
3152 	pkt.fp_statuscb = fwohci_read_resp;
3153 
3154 	rv = fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
3155 	    psc->sc_tlabel, fwohci_read_resp, fcb);
3156 	if (rv)
3157 		return rv;
3158 	rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
3159 	if (rv)
3160 		fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
3161 		    psc->sc_tlabel, NULL, NULL);
3162 	psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
3163 	fcb->count = 1;
3164 	return rv;
3165 }
3166 
3167 static int
3168 fwohci_write(struct ieee1394_abuf *ab)
3169 {
3170 	struct fwohci_pkt pkt;
3171 	struct ieee1394_softc *sc = ab->ab_req;
3172 	struct fwohci_softc *psc =
3173 	    (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3174 	u_int32_t high, lo;
3175 	int rv;
3176 
3177 	if (ab->ab_length > sc->sc1394_max_receive) {
3178 		DPRINTF(("Packet too large: %d\n", ab->ab_length));
3179 		return E2BIG;
3180 	}
3181 
3182 	memset(&pkt, 0, sizeof(pkt));
3183 
3184 	pkt.fp_tcode = ab->ab_tcode;
3185 	pkt.fp_uio.uio_iov = pkt.fp_iov;
3186 	pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
3187 	pkt.fp_uio.uio_rw = UIO_WRITE;
3188 
3189 	pkt.fp_statusarg = ab;
3190 	pkt.fp_statuscb = fwohci_write_ack;
3191 
3192 	switch (ab->ab_tcode) {
3193 	case IEEE1394_TCODE_WRITE_RESP:
3194 		pkt.fp_hlen = 12;
3195 	case IEEE1394_TCODE_READ_RESP_QUAD:
3196 	case IEEE1394_TCODE_READ_RESP_BLOCK:
3197 		if (!pkt.fp_hlen)
3198 			pkt.fp_hlen = 16;
3199 		high = ab->ab_retlen;
3200 		ab->ab_retlen = 0;
3201 		lo = 0;
3202 		pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3203 		    (ab->ab_tlabel << 10) | (pkt.fp_tcode << 4);
3204 		break;
3205 	default:
3206 		pkt.fp_hlen = 16;
3207 		high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3208 		lo = (ab->ab_csr & 0x00000000ffffffff);
3209 		pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3210 		    (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
3211 		break;
3212 	}
3213 
3214 	pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3215 	pkt.fp_hdr[2] = lo;
3216 	if (pkt.fp_hlen == 16) {
3217 		if (ab->ab_length == 4) {
3218 			pkt.fp_hdr[3] = ab->ab_data[0];
3219 			pkt.fp_dlen = 0;
3220 		}  else {
3221 			pkt.fp_hdr[3] = (ab->ab_length << 16);
3222 			pkt.fp_dlen = ab->ab_length;
3223 			pkt.fp_uio.uio_iovcnt = 1;
3224 			pkt.fp_uio.uio_resid = ab->ab_length;
3225 			pkt.fp_iov[0].iov_base = ab->ab_data;
3226 			pkt.fp_iov[0].iov_len = ab->ab_length;
3227 		}
3228 	}
3229 	switch (ab->ab_tcode) {
3230 	case IEEE1394_TCODE_WRITE_RESP:
3231 	case IEEE1394_TCODE_READ_RESP_QUAD:
3232 	case IEEE1394_TCODE_READ_RESP_BLOCK:
3233 		rv = fwohci_at_output(psc, psc->sc_ctx_atrs, &pkt);
3234 		break;
3235 	default:
3236 		rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
3237 		break;
3238 	}
3239 	return rv;
3240 }
3241 
3242 static int
3243 fwohci_read_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3244 {
3245 	struct fwohci_cb *fcb = arg;
3246 	struct ieee1394_abuf *ab = fcb->ab;
3247 	struct fwohci_pkt newpkt;
3248 	u_int32_t *cur, high, lo;
3249 	int i, tcode, rcode, status, rv;
3250 
3251 	/*
3252 	 * Both the ACK handling and normal response callbacks are handled here.
3253 	 * The main reason for this is the various error conditions that can
3254 	 * occur trying to block read some areas and the ways that gets reported
3255 	 * back to calling station. This is a variety of ACK codes, responses,
3256 	 * etc which makes it much more difficult to process if both aren't
3257 	 * handled here.
3258 	 */
3259 
3260 	/* Check for status packet. */
3261 
3262 	if (pkt->fp_tcode == -1) {
3263 		status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
3264 		rcode = -1;
3265 		tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
3266 		if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3267 		    (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
3268 			DPRINTF(("Got status packet: 0x%02x\n",
3269 			    (unsigned int)status));
3270 		fcb->count--;
3271 
3272 		/*
3273 		 * Got all the ack's back and the buffer is invalid (i.e. the
3274 		 * callback has been called. Clean up.
3275 		 */
3276 
3277 		if (fcb->abuf_valid == 0) {
3278 			if (fcb->count == 0)
3279 				free(fcb, M_DEVBUF);
3280 			return IEEE1394_RCODE_COMPLETE;
3281 		}
3282 	} else {
3283 		status = -1;
3284 		tcode = pkt->fp_tcode;
3285 		rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
3286 	}
3287 
3288 	/*
3289 	 * Some area's (like the config rom want to be read as quadlets only.
3290 	 *
3291 	 * The current ideas to try are:
3292 	 *
3293 	 * Got an ACK_TYPE_ERROR on a block read.
3294 	 *
3295 	 * Got either RCODE_TYPE or RCODE_ADDRESS errors in a block read
3296 	 * response.
3297 	 *
3298 	 * In all cases construct a new packet for a quadlet read and let
3299 	 * mutli_resp handle the iteration over the space.
3300 	 */
3301 
3302 	if (((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) &&
3303 	     (tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) ||
3304 	    (((rcode == IEEE1394_RCODE_TYPE_ERROR) ||
3305 	     (rcode == IEEE1394_RCODE_ADDRESS_ERROR)) &&
3306 	      (tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) {
3307 
3308 		/* Read the area in quadlet chunks (internally track this). */
3309 
3310 		memset(&newpkt, 0, sizeof(newpkt));
3311 
3312 		high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3313 		lo = (ab->ab_csr & 0x00000000ffffffff);
3314 
3315 		newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3316 		newpkt.fp_hlen = 12;
3317 		newpkt.fp_dlen = 0;
3318 		newpkt.fp_hdr[1] =
3319 		    ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3320 		newpkt.fp_hdr[2] = lo;
3321 		newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
3322 		    (newpkt.fp_tcode << 4);
3323 
3324 		rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3325 		    ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3326 		    fwohci_read_multi_resp, fcb);
3327 		if (rv) {
3328 			(*ab->ab_cb)(ab, -1);
3329 			goto cleanup;
3330 		}
3331 		newpkt.fp_statusarg = fcb;
3332 		newpkt.fp_statuscb = fwohci_read_resp;
3333 		rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
3334 		if (rv) {
3335 			fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3336 			    ab->ab_req->sc1394_node_id, sc->sc_tlabel, NULL,
3337 			    NULL);
3338 			(*ab->ab_cb)(ab, -1);
3339 			goto cleanup;
3340 		}
3341 		fcb->count++;
3342 		sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3343 		return IEEE1394_RCODE_COMPLETE;
3344 	} else if ((rcode != -1) || ((status != -1) &&
3345 	    (status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3346 	    (status != OHCI_CTXCTL_EVENT_ACK_PENDING))) {
3347 
3348 		/*
3349 		 * Recombine all the iov data into 1 chunk for higher
3350 		 * level code.
3351 		 */
3352 
3353 		if (rcode != -1) {
3354 			cur = ab->ab_data;
3355 			for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
3356 				/*
3357 				 * Make sure and don't exceed the buffer
3358 				 * allocated for return.
3359 				 */
3360 				if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) >
3361 				    ab->ab_length) {
3362 					memcpy(cur, pkt->fp_iov[i].iov_base,
3363 					    (ab->ab_length - ab->ab_retlen));
3364 					ab->ab_retlen = ab->ab_length;
3365 					break;
3366 				}
3367 				memcpy(cur, pkt->fp_iov[i].iov_base,
3368 				    pkt->fp_iov[i].iov_len);
3369 				cur += pkt->fp_iov[i].iov_len;
3370 				ab->ab_retlen += pkt->fp_iov[i].iov_len;
3371 			}
3372 		}
3373 		if (status != -1)
3374 			/* XXX: Need a complete tlabel interface. */
3375 			for (i = 0; i < 64; i++)
3376 				fwohci_handler_set(sc,
3377 				    IEEE1394_TCODE_READ_RESP_QUAD,
3378 				    ab->ab_req->sc1394_node_id, i, NULL, NULL);
3379 		(*ab->ab_cb)(ab, rcode);
3380 		goto cleanup;
3381 	} else
3382 		/* Good ack packet. */
3383 		return IEEE1394_RCODE_COMPLETE;
3384 
3385 	/* Can't get here unless ab->ab_cb has been called. */
3386 
3387  cleanup:
3388 	fcb->abuf_valid = 0;
3389 	if (fcb->count == 0)
3390 		free(fcb, M_DEVBUF);
3391 	return IEEE1394_RCODE_COMPLETE;
3392 }
3393 
3394 static int
3395 fwohci_read_multi_resp(struct fwohci_softc *sc, void *arg,
3396     struct fwohci_pkt *pkt)
3397 {
3398 	struct fwohci_cb *fcb = arg;
3399 	struct ieee1394_abuf *ab = fcb->ab;
3400 	struct fwohci_pkt newpkt;
3401 	u_int32_t high, lo;
3402 	int rcode, rv;
3403 
3404 	/*
3405 	 * Bad return codes from the wire, just return what's already in the
3406 	 * buf.
3407 	 */
3408 
3409 	/* Make sure a response packet didn't arrive after a bad ACK. */
3410 	if (fcb->abuf_valid == 0)
3411 		return IEEE1394_RCODE_COMPLETE;
3412 
3413 	rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
3414 
3415 	if (rcode) {
3416 		(*ab->ab_cb)(ab, rcode);
3417 		goto cleanup;
3418 	}
3419 
3420 	if ((ab->ab_retlen + pkt->fp_iov[0].iov_len) > ab->ab_length) {
3421 		memcpy(((char *)ab->ab_data + ab->ab_retlen),
3422 		    pkt->fp_iov[0].iov_base, (ab->ab_length - ab->ab_retlen));
3423 		ab->ab_retlen = ab->ab_length;
3424 	} else {
3425 		memcpy(((char *)ab->ab_data + ab->ab_retlen),
3426 		    pkt->fp_iov[0].iov_base, 4);
3427 		ab->ab_retlen += 4;
3428 	}
3429 	/* Still more, loop and read 4 more bytes. */
3430 	if (ab->ab_retlen < ab->ab_length) {
3431 		memset(&newpkt, 0, sizeof(newpkt));
3432 
3433 		high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3434 		lo = (ab->ab_csr & 0x00000000ffffffff) + ab->ab_retlen;
3435 
3436 		newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3437 		newpkt.fp_hlen = 12;
3438 		newpkt.fp_dlen = 0;
3439 		newpkt.fp_hdr[1] =
3440 		    ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3441 		newpkt.fp_hdr[2] = lo;
3442 		newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
3443 		    (newpkt.fp_tcode << 4);
3444 
3445 		newpkt.fp_statusarg = fcb;
3446 		newpkt.fp_statuscb = fwohci_read_resp;
3447 
3448 		/*
3449 		 * Bad return code.  Just give up and return what's
3450 		 * come in now.
3451 		 */
3452 		rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3453 		    ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3454 		    fwohci_read_multi_resp, fcb);
3455 		if (rv)
3456 			(*ab->ab_cb)(ab, -1);
3457 		else {
3458 			rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
3459 			if (rv) {
3460 				fwohci_handler_set(sc,
3461 				    IEEE1394_TCODE_READ_RESP_QUAD,
3462 				    ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3463 				    NULL, NULL);
3464 				(*ab->ab_cb)(ab, -1);
3465 			} else {
3466 				sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3467 				fcb->count++;
3468 				return IEEE1394_RCODE_COMPLETE;
3469 			}
3470 		}
3471 	} else
3472 		(*ab->ab_cb)(ab, IEEE1394_RCODE_COMPLETE);
3473 
3474  cleanup:
3475 	/* Can't get here unless ab_cb has been called. */
3476 	fcb->abuf_valid = 0;
3477 	if (fcb->count == 0)
3478 		free(fcb, M_DEVBUF);
3479 	return IEEE1394_RCODE_COMPLETE;
3480 }
3481 
3482 static int
3483 fwohci_write_ack(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3484 {
3485 	struct ieee1394_abuf *ab = arg;
3486 	u_int16_t status;
3487 
3488 
3489 	status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
3490 	if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3491 	    (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
3492 		DPRINTF(("Got status packet: 0x%02x\n",
3493 		    (unsigned int)status));
3494 
3495 	/* No callback means this level should free the buffers. */
3496 	if (ab->ab_cb)
3497 		(*ab->ab_cb)(ab, status);
3498 	else {
3499 		if (ab->ab_data)
3500 			free(ab->ab_data, M_1394DATA);
3501 		free(ab, M_1394DATA);
3502 	}
3503 	return IEEE1394_RCODE_COMPLETE;
3504 }
3505 
3506 static int
3507 fwohci_inreg(struct ieee1394_abuf *ab, int allow)
3508 {
3509 	struct ieee1394_softc *sc = ab->ab_req;
3510 	struct fwohci_softc *psc =
3511 	    (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3512 	u_int32_t high, lo;
3513 	int i, j, rv;
3514 
3515 	high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3516 	lo = (ab->ab_csr & 0x00000000ffffffff);
3517 
3518 	rv = 0;
3519 	switch (ab->ab_tcode) {
3520 	case IEEE1394_TCODE_READ_REQ_QUAD:
3521 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
3522 		if (ab->ab_cb)
3523 			rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo,
3524 			    fwohci_parse_input, ab);
3525 		else
3526 			fwohci_handler_set(psc, ab->ab_tcode, high, lo, NULL,
3527 			    NULL);
3528 		break;
3529 	case IEEE1394_TCODE_READ_REQ_BLOCK:
3530 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
3531 		if (allow) {
3532 			for (i = 0; i < (ab->ab_length / 4); i++) {
3533 				if (ab->ab_cb) {
3534 					rv = fwohci_handler_set(psc,
3535 					    ab->ab_tcode, high, lo + (i * 4),
3536 					    fwohci_parse_input, ab);
3537 					if (rv)
3538 						break;
3539 				} else
3540 					fwohci_handler_set(psc, ab->ab_tcode,
3541 					    high, lo + (i * 4), NULL, NULL);
3542 			}
3543 			if (i != (ab->ab_length / 4)) {
3544 				j = i + 1;
3545 				for (i = 0; i < j; i++)
3546 					fwohci_handler_set(psc, ab->ab_tcode,
3547 					    high, lo + (i * 4), NULL, NULL);
3548 			} else
3549 				ab->ab_data = (void *)1;
3550 		} else {
3551 			if (ab->ab_cb)
3552 				rv = fwohci_handler_set(psc, ab->ab_tcode, high,
3553 				    lo, fwohci_parse_input, ab);
3554 			else
3555 				fwohci_handler_set(psc, ab->ab_tcode, high, lo,
3556 				    NULL, NULL);
3557 		}
3558 		break;
3559 	default:
3560 		DPRINTF(("Invalid registration tcode: %d\n", ab->ab_tcode));
3561 		return -1;
3562 		break;
3563 	}
3564 	return rv;
3565 }
3566 
3567 static int
3568 fwohci_parse_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3569 {
3570 	struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg;
3571 	u_int64_t csr;
3572 	u_int32_t *cur;
3573 	int i, count;
3574 
3575 	ab->ab_tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
3576 	ab->ab_tlabel = (pkt->fp_hdr[0] >> 10) & 0x3f;
3577 	csr = (((u_int64_t)(pkt->fp_hdr[1] & 0xffff) << 32) | pkt->fp_hdr[2]);
3578 
3579 	switch (ab->ab_tcode) {
3580 	case IEEE1394_TCODE_READ_REQ_QUAD:
3581 		ab->ab_retlen = 4;
3582 		break;
3583 	case IEEE1394_TCODE_READ_REQ_BLOCK:
3584 		ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
3585 		if (ab->ab_data) {
3586 			if ((csr + ab->ab_retlen) >
3587 			    (ab->ab_csr + ab->ab_length))
3588 				return IEEE1394_RCODE_ADDRESS_ERROR;
3589 			ab->ab_data = NULL;
3590 		} else
3591 			if (ab->ab_retlen != ab->ab_length)
3592 				return IEEE1394_RCODE_ADDRESS_ERROR;
3593 		break;
3594 	case IEEE1394_TCODE_WRITE_REQ_QUAD:
3595 		ab->ab_retlen = 4;
3596 	case IEEE1394_TCODE_WRITE_REQ_BLOCK:
3597 		if (!ab->ab_retlen)
3598 			ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
3599 		if (ab->ab_data) {
3600 			if ((csr + ab->ab_retlen) >
3601 			    (ab->ab_csr + ab->ab_length))
3602 				return IEEE1394_RCODE_ADDRESS_ERROR;
3603 			ab->ab_data = NULL;
3604 		} else
3605 			if (ab->ab_retlen != ab->ab_length)
3606 				return IEEE1394_RCODE_ADDRESS_ERROR;
3607 
3608 		ab->ab_data = malloc(ab->ab_retlen, M_1394DATA, M_WAITOK);
3609 		if (ab->ab_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD)
3610 			ab->ab_data[0] = pkt->fp_hdr[3];
3611 		else {
3612 			count = 0;
3613 			cur = ab->ab_data;
3614 			for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
3615 				memcpy(cur, pkt->fp_iov[i].iov_base,
3616 				    pkt->fp_iov[i].iov_len);
3617 				cur += pkt->fp_iov[i].iov_len;
3618 				count += pkt->fp_iov[i].iov_len;
3619 			}
3620 			if (ab->ab_retlen != count)
3621 				panic("Packet claims %d length "
3622 				    "but only %d bytes returned\n",
3623 				    ab->ab_retlen, count);
3624 		}
3625 		break;
3626 	default:
3627 		panic("Got a callback for a tcode that wasn't requested: %d\n",
3628 		    ab->ab_tcode);
3629 		break;
3630 	}
3631 	ab->ab_csr = csr;
3632 	ab->ab_cb(ab, IEEE1394_RCODE_COMPLETE);
3633 	return -1;
3634 }
3635 
3636 static int
3637 fwohci_submatch(struct device *parent, struct cfdata *cf, void *aux)
3638 {
3639 	struct ieee1394_attach_args *fwa = aux;
3640 
3641 	/* Both halves must be filled in for a match. */
3642 	if ((cf->fwbuscf_idhi == FWBUS_UNK_IDHI &&
3643 	    cf->fwbuscf_idlo == FWBUS_UNK_IDLO) ||
3644 	    (cf->fwbuscf_idhi == ntohl(*((u_int32_t *)&fwa->uid[0])) &&
3645 	    cf->fwbuscf_idlo == ntohl(*((u_int32_t *)&fwa->uid[4]))))
3646 		return ((*cf->cf_attach->ca_match)(parent, cf, aux));
3647 	return 0;
3648 }
3649 
3650 #ifdef FW_DEBUG
3651 static void
3652 fwohci_show_intr(struct fwohci_softc *sc, u_int32_t intmask)
3653 {
3654 
3655 	printf("%s: intmask=0x%08x:", sc->sc_sc1394.sc1394_dev.dv_xname,
3656 	    intmask);
3657 	if (intmask & OHCI_Int_CycleTooLong)
3658 		printf(" CycleTooLong");
3659 	if (intmask & OHCI_Int_UnrecoverableError)
3660 		printf(" UnrecoverableError");
3661 	if (intmask & OHCI_Int_CycleInconsistent)
3662 		printf(" CycleInconsistent");
3663 	if (intmask & OHCI_Int_BusReset)
3664 		printf(" BusReset");
3665 	if (intmask & OHCI_Int_SelfIDComplete)
3666 		printf(" SelfIDComplete");
3667 	if (intmask & OHCI_Int_LockRespErr)
3668 		printf(" LockRespErr");
3669 	if (intmask & OHCI_Int_PostedWriteErr)
3670 		printf(" PostedWriteErr");
3671 	if (intmask & OHCI_Int_ReqTxComplete)
3672 		printf(" ReqTxComplete(0x%04x)",
3673 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
3674 		    OHCI_SUBREG_ContextControlClear));
3675 	if (intmask & OHCI_Int_RespTxComplete)
3676 		printf(" RespTxComplete(0x%04x)",
3677 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
3678 		    OHCI_SUBREG_ContextControlClear));
3679 	if (intmask & OHCI_Int_ARRS)
3680 		printf(" ARRS(0x%04x)",
3681 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
3682 		    OHCI_SUBREG_ContextControlClear));
3683 	if (intmask & OHCI_Int_ARRQ)
3684 		printf(" ARRQ(0x%04x)",
3685 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
3686 		    OHCI_SUBREG_ContextControlClear));
3687 	if (intmask & OHCI_Int_IsochRx)
3688 		printf(" IsochRx(0x%08x)",
3689 		    OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear));
3690 	if (intmask & OHCI_Int_IsochTx)
3691 		printf(" IsochTx(0x%08x)",
3692 		    OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear));
3693 	if (intmask & OHCI_Int_RQPkt)
3694 		printf(" RQPkt(0x%04x)",
3695 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
3696 		    OHCI_SUBREG_ContextControlClear));
3697 	if (intmask & OHCI_Int_RSPkt)
3698 		printf(" RSPkt(0x%04x)",
3699 		    OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
3700 		    OHCI_SUBREG_ContextControlClear));
3701 	printf("\n");
3702 }
3703 
3704 static void
3705 fwohci_show_phypkt(struct fwohci_softc *sc, u_int32_t val)
3706 {
3707 	u_int8_t key, phyid;
3708 
3709 	key = (val & 0xc0000000) >> 30;
3710 	phyid = (val & 0x3f000000) >> 24;
3711 	printf("%s: PHY packet from %d: ",
3712 	    sc->sc_sc1394.sc1394_dev.dv_xname, phyid);
3713 	switch (key) {
3714 	case 0:
3715 		printf("PHY Config:");
3716 		if (val & 0x00800000)
3717 			printf(" ForceRoot");
3718 		if (val & 0x00400000)
3719 			printf(" Gap=%x", (val & 0x003f0000) >> 16);
3720 		printf("\n");
3721 		break;
3722 	case 1:
3723 		printf("Link-on\n");
3724 		break;
3725 	case 2:
3726 		printf("SelfID:");
3727 		if (val & 0x00800000) {
3728 			printf(" #%d", (val & 0x00700000) >> 20);
3729 		} else {
3730 			if (val & 0x00400000)
3731 				printf(" LinkActive");
3732 			printf(" Gap=%x", (val & 0x003f0000) >> 16);
3733 			printf(" Spd=S%d", 100 << ((val & 0x0000c000) >> 14));
3734 			if (val & 0x00000800)
3735 				printf(" Cont");
3736 			if (val & 0x00000002)
3737 				printf(" InitiateBusReset");
3738 		}
3739 		if (val & 0x00000001)
3740 			printf(" +");
3741 		printf("\n");
3742 		break;
3743 	default:
3744 		printf("unknown: 0x%08x\n", val);
3745 		break;
3746 	}
3747 }
3748 #endif /* FW_DEBUG */
3749