fwohci.c revision 1.43 1 /* $NetBSD: fwohci.c,v 1.43 2001/09/18 16:11:00 tsutsui 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 (at) netbsd.org>.
46 */
47
48 /*
49 * The first version to support isochronous acquisition part is wrtten
50 * by HAYAKAWA Koichi <haya (at) 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 #if DOUBLEBUF
1024 if (TAILQ_FIRST(&fc->fc_buf) > TAILQ_FIRST(&fc->fc_buf2)) {
1025 struct fwohci_buf_s fctmp;
1026
1027 fctmp = fc->fc_buf;
1028 fc->fc_buf = fc->fc_buf2;
1029 fc->fc_buf2 = fctmp;
1030 }
1031 #endif
1032 while ((fh = LIST_FIRST(&fc->fc_handler)) != NULL)
1033 fwohci_handler_set(sc, fh->fh_tcode, fh->fh_key1, fh->fh_key2,
1034 NULL, NULL);
1035 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1036 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
1037 if (fb->fb_desc)
1038 fwohci_desc_put(sc, fb->fb_desc, 1);
1039 fwohci_buf_free(sc, fb);
1040 }
1041 #if DOUBLEBUF
1042 while ((fb = TAILQ_FIRST(&fc->fc_buf2)) != NULL) {
1043 TAILQ_REMOVE(&fc->fc_buf2, fb, fb_list);
1044 if (fb->fb_desc)
1045 fwohci_desc_put(sc, fb->fb_desc, 1);
1046 fwohci_buf_free(sc, fb);
1047 }
1048 #endif /* DOUBLEBUF */
1049 free(fc, M_DEVBUF);
1050 }
1051
1052 static void
1053 fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1054 {
1055 struct fwohci_buf *fb, *nfb;
1056 struct fwohci_desc *fd;
1057 struct fwohci_handler *fh;
1058 int n;
1059
1060 for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; fb = nfb) {
1061 nfb = TAILQ_NEXT(fb, fb_list);
1062 fb->fb_off = 0;
1063 fd = fb->fb_desc;
1064 fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
1065 fd->fd_rescount = fd->fd_reqcount;
1066 }
1067
1068 #if DOUBLEBUF
1069 for (fb = TAILQ_FIRST(&fc->fc_buf2); fb != NULL; fb = nfb) {
1070 bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
1071 (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
1072 BUS_DMASYNC_PREWRITE);
1073 nfb = TAILQ_NEXT(fb, fb_list);
1074 fb->fb_off = 0;
1075 fd = fb->fb_desc;
1076 fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
1077 fd->fd_rescount = fd->fd_reqcount;
1078 bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap,
1079 (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc),
1080 BUS_DMASYNC_POSTWRITE);
1081 }
1082 #endif /* DOUBLEBUF */
1083
1084 n = fc->fc_ctx;
1085 fb = TAILQ_FIRST(&fc->fc_buf);
1086 if (fc->fc_type != FWOHCI_CTX_ASYNC) {
1087 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
1088 fb->fb_daddr | 1);
1089 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear,
1090 OHCI_CTXCTL_RX_BUFFER_FILL |
1091 OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE |
1092 OHCI_CTXCTL_RX_MULTI_CHAN_MODE |
1093 OHCI_CTXCTL_RX_DUAL_BUFFER_MODE);
1094 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet,
1095 OHCI_CTXCTL_RX_ISOCH_HEADER);
1096 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) {
1097 OHCI_SYNC_RX_DMA_WRITE(sc, n,
1098 OHCI_SUBREG_ContextControlSet,
1099 OHCI_CTXCTL_RX_BUFFER_FILL);
1100 }
1101 fh = LIST_FIRST(&fc->fc_handler);
1102 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextMatch,
1103 (OHCI_CTXMATCH_TAG0 << fh->fh_key2) | fh->fh_key1);
1104 } else {
1105 OHCI_ASYNC_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
1106 fb->fb_daddr | 1);
1107 }
1108 }
1109
1110 /*
1111 * DMA data buffer
1112 */
1113 static int
1114 fwohci_buf_alloc(struct fwohci_softc *sc, struct fwohci_buf *fb)
1115 {
1116 int error;
1117
1118 if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
1119 PAGE_SIZE, &fb->fb_seg, 1, &fb->fb_nseg, BUS_DMA_WAITOK)) != 0) {
1120 printf("%s: unable to allocate buffer, error = %d\n",
1121 sc->sc_sc1394.sc1394_dev.dv_xname, error);
1122 goto fail_0;
1123 }
1124
1125 if ((error = bus_dmamem_map(sc->sc_dmat, &fb->fb_seg,
1126 fb->fb_nseg, PAGE_SIZE, &fb->fb_buf, BUS_DMA_WAITOK)) != 0) {
1127 printf("%s: unable to map buffer, error = %d\n",
1128 sc->sc_sc1394.sc1394_dev.dv_xname, error);
1129 goto fail_1;
1130 }
1131
1132 if ((error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, fb->fb_nseg,
1133 PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) {
1134 printf("%s: unable to create buffer DMA map, "
1135 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
1136 error);
1137 goto fail_2;
1138 }
1139
1140 if ((error = bus_dmamap_load(sc->sc_dmat, fb->fb_dmamap,
1141 fb->fb_buf, PAGE_SIZE, NULL, BUS_DMA_WAITOK)) != 0) {
1142 printf("%s: unable to load buffer DMA map, "
1143 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
1144 error);
1145 goto fail_3;
1146 }
1147
1148 return 0;
1149
1150 bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
1151 fail_3:
1152 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1153 fail_2:
1154 bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
1155 fail_1:
1156 bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
1157 fail_0:
1158 return error;
1159 }
1160
1161 static void
1162 fwohci_buf_free(struct fwohci_softc *sc, struct fwohci_buf *fb)
1163 {
1164
1165 bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
1166 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1167 bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
1168 bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
1169 }
1170
1171 static void
1172 fwohci_buf_init_rx(struct fwohci_softc *sc)
1173 {
1174 int i;
1175
1176 /*
1177 * Initialize for Asynchronous Receive Queue.
1178 */
1179 fwohci_ctx_init(sc, sc->sc_ctx_arrq);
1180 fwohci_ctx_init(sc, sc->sc_ctx_arrs);
1181
1182 /*
1183 * Initialize for Isochronous Receive Queue.
1184 */
1185 for (i = 0; i < sc->sc_isoctx; i++) {
1186 if (sc->sc_ctx_ir[i] != NULL)
1187 fwohci_ctx_init(sc, sc->sc_ctx_ir[i]);
1188 }
1189 }
1190
1191 static void
1192 fwohci_buf_start_rx(struct fwohci_softc *sc)
1193 {
1194 int i;
1195
1196 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
1197 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1198 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
1199 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1200 for (i = 0; i < sc->sc_isoctx; i++) {
1201 if (sc->sc_ctx_ir[i] != NULL)
1202 OHCI_SYNC_RX_DMA_WRITE(sc, i,
1203 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1204 }
1205 }
1206
1207 static void
1208 fwohci_buf_stop_tx(struct fwohci_softc *sc)
1209 {
1210 int i;
1211
1212 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_REQUEST,
1213 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1214 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
1215 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1216
1217 /*
1218 * Make sure the transmitter is stopped.
1219 */
1220 for (i = 0; i < OHCI_LOOP; i++) {
1221 DELAY(10);
1222 if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
1223 OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
1224 continue;
1225 if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
1226 OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
1227 continue;
1228 break;
1229 }
1230
1231 /*
1232 * Initialize for Asynchronous Transmit Queue.
1233 */
1234 fwohci_at_done(sc, sc->sc_ctx_atrq, 1);
1235 fwohci_at_done(sc, sc->sc_ctx_atrs, 1);
1236 }
1237
1238 static void
1239 fwohci_buf_stop_rx(struct fwohci_softc *sc)
1240 {
1241 int i;
1242
1243 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
1244 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1245 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
1246 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1247 for (i = 0; i < sc->sc_isoctx; i++) {
1248 OHCI_SYNC_RX_DMA_WRITE(sc, i,
1249 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1250 }
1251 }
1252
1253 static void
1254 fwohci_buf_next(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1255 {
1256 struct fwohci_buf *fb, *tfb;
1257
1258 #if DOUBLEBUF
1259 if (fc->fc_type != FWOHCI_CTX_ISO_MULTI) {
1260 #endif
1261 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1262 if (fc->fc_type) {
1263 if (fb->fb_off == 0)
1264 break;
1265 } else {
1266 if (fb->fb_off != fb->fb_desc->fd_reqcount ||
1267 fb->fb_desc->fd_rescount != 0)
1268 break;
1269 }
1270 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
1271 fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
1272 fb->fb_off = 0;
1273 fb->fb_desc->fd_branch = 0;
1274 tfb = TAILQ_LAST(&fc->fc_buf, fwohci_buf_s);
1275 tfb->fb_desc->fd_branch = fb->fb_daddr | 1;
1276 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
1277 }
1278 #if DOUBLEBUF
1279 } else {
1280 struct fwohci_buf_s fctmp;
1281
1282 /* cleaning buffer */
1283 for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL;
1284 fb = TAILQ_NEXT(fb, fb_list)) {
1285 fb->fb_off = 0;
1286 fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
1287 }
1288
1289 /* rotating buffer */
1290 fctmp = fc->fc_buf;
1291 fc->fc_buf = fc->fc_buf2;
1292 fc->fc_buf2 = fctmp;
1293 }
1294 #endif
1295 }
1296
1297 static int
1298 fwohci_buf_pktget(struct fwohci_softc *sc, struct fwohci_buf **fbp, caddr_t *pp,
1299 int len)
1300 {
1301 struct fwohci_buf *fb;
1302 struct fwohci_desc *fd;
1303 int bufend;
1304
1305 fb = *fbp;
1306 again:
1307 fd = fb->fb_desc;
1308 DPRINTFN(1, ("fwohci_buf_pktget: desc %ld, off %d, req %d, res %d,"
1309 " len %d, avail %d\n", (long)(fd - sc->sc_desc), fb->fb_off,
1310 fd->fd_reqcount, fd->fd_rescount, len,
1311 fd->fd_reqcount - fd->fd_rescount - fb->fb_off));
1312 bufend = fd->fd_reqcount - fd->fd_rescount;
1313 if (fb->fb_off >= bufend) {
1314 DPRINTFN(5, ("buf %x finish req %d res %d off %d ",
1315 fb->fb_desc->fd_data, fd->fd_reqcount, fd->fd_rescount,
1316 fb->fb_off));
1317 if (fd->fd_rescount == 0) {
1318 *fbp = fb = TAILQ_NEXT(fb, fb_list);
1319 if (fb != NULL)
1320 goto again;
1321 }
1322 return 0;
1323 }
1324 if (fb->fb_off + len > bufend)
1325 len = bufend - fb->fb_off;
1326 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
1327 BUS_DMASYNC_POSTREAD);
1328 *pp = fb->fb_buf + fb->fb_off;
1329 fb->fb_off += roundup(len, 4);
1330 return len;
1331 }
1332
1333 static int
1334 fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1335 struct fwohci_pkt *pkt)
1336 {
1337 caddr_t p;
1338 struct fwohci_buf *fb;
1339 int len, count, i;
1340
1341 memset(pkt, 0, sizeof(*pkt));
1342 pkt->fp_uio.uio_iov = pkt->fp_iov;
1343 pkt->fp_uio.uio_rw = UIO_WRITE;
1344 pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
1345
1346 /* get first quadlet */
1347 fb = TAILQ_FIRST(&fc->fc_buf);
1348 count = 4;
1349 len = fwohci_buf_pktget(sc, &fb, &p, count);
1350 if (len <= 0) {
1351 DPRINTFN(1, ("fwohci_buf_input: no input for %d\n",
1352 fc->fc_ctx));
1353 return 0;
1354 }
1355 pkt->fp_hdr[0] = *(u_int32_t *)p;
1356 pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
1357 switch (pkt->fp_tcode) {
1358 case IEEE1394_TCODE_WRITE_REQ_QUAD:
1359 case IEEE1394_TCODE_READ_RESP_QUAD:
1360 pkt->fp_hlen = 12;
1361 pkt->fp_dlen = 4;
1362 break;
1363 case IEEE1394_TCODE_READ_REQ_BLOCK:
1364 pkt->fp_hlen = 16;
1365 pkt->fp_dlen = 0;
1366 break;
1367 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1368 case IEEE1394_TCODE_READ_RESP_BLOCK:
1369 case IEEE1394_TCODE_LOCK_REQ:
1370 case IEEE1394_TCODE_LOCK_RESP:
1371 pkt->fp_hlen = 16;
1372 break;
1373 case IEEE1394_TCODE_STREAM_DATA:
1374 #ifdef DIAGNOSTIC
1375 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI)
1376 #endif
1377 {
1378 pkt->fp_hlen = 4;
1379 pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
1380 DPRINTFN(5, ("[%d]", pkt->fp_dlen));
1381 break;
1382 }
1383 #ifdef DIAGNOSTIC
1384 else {
1385 printf("fwohci_buf_input: bad tcode: STREAM_DATA\n");
1386 return 0;
1387 }
1388 #endif
1389 default:
1390 pkt->fp_hlen = 12;
1391 pkt->fp_dlen = 0;
1392 break;
1393 }
1394
1395 /* get header */
1396 while (count < pkt->fp_hlen) {
1397 len = fwohci_buf_pktget(sc, &fb, &p, pkt->fp_hlen - count);
1398 if (len == 0) {
1399 printf("fwohci_buf_input: malformed input 1: %d\n",
1400 pkt->fp_hlen - count);
1401 return 0;
1402 }
1403 memcpy((caddr_t)pkt->fp_hdr + count, p, len);
1404 count += len;
1405 }
1406 if (pkt->fp_hlen == 16 &&
1407 pkt->fp_tcode != IEEE1394_TCODE_READ_REQ_BLOCK)
1408 pkt->fp_dlen = pkt->fp_hdr[3] >> 16;
1409 DPRINTFN(1, ("fwohci_buf_input: tcode=0x%x, hlen=%d, dlen=%d\n",
1410 pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
1411
1412 /* get data */
1413 count = 0;
1414 i = 0;
1415 while (count < pkt->fp_dlen) {
1416 len = fwohci_buf_pktget(sc, &fb,
1417 (caddr_t *)&pkt->fp_iov[i].iov_base,
1418 pkt->fp_dlen - count);
1419 if (len == 0) {
1420 printf("fwohci_buf_input: malformed input 2: %d\n",
1421 pkt->fp_dlen - count);
1422 return 0;
1423 }
1424 pkt->fp_iov[i++].iov_len = len;
1425 count += len;
1426 }
1427 pkt->fp_uio.uio_iovcnt = i;
1428 pkt->fp_uio.uio_resid = count;
1429
1430 /* get trailer */
1431 len = fwohci_buf_pktget(sc, &fb, (caddr_t *)&pkt->fp_trail,
1432 sizeof(*pkt->fp_trail));
1433 if (len <= 0) {
1434 printf("fwohci_buf_input: malformed input 3: %d\n",
1435 pkt->fp_hlen - count);
1436 return 0;
1437 }
1438 return 1;
1439 }
1440
1441 static int
1442 fwohci_buf_input_ppb(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1443 struct fwohci_pkt *pkt)
1444 {
1445 caddr_t p;
1446 int len;
1447 struct fwohci_buf *fb;
1448 struct fwohci_desc *fd;
1449
1450 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) {
1451 return fwohci_buf_input(sc, fc, pkt);
1452 }
1453
1454 memset(pkt, 0, sizeof(*pkt));
1455 pkt->fp_uio.uio_iov = pkt->fp_iov;
1456 pkt->fp_uio.uio_rw = UIO_WRITE;
1457 pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
1458
1459 for (fb = TAILQ_FIRST(&fc->fc_buf); ; fb = TAILQ_NEXT(fb, fb_list)) {
1460 if (fb == NULL)
1461 return 0;
1462 if (fb->fb_off == 0)
1463 break;
1464 }
1465 fd = fb->fb_desc;
1466 len = fd->fd_reqcount - fd->fd_rescount;
1467 if (len == 0)
1468 return 0;
1469 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
1470 BUS_DMASYNC_POSTREAD);
1471
1472 p = fb->fb_buf;
1473 fb->fb_off += roundup(len, 4);
1474 if (len < 8) {
1475 printf("fwohci_buf_input_ppb: malformed input 1: %d\n", len);
1476 return 0;
1477 }
1478
1479 /*
1480 * get trailer first, may be bogus data unless status update
1481 * in descriptor is set.
1482 */
1483 pkt->fp_trail = (u_int32_t *)p;
1484 *pkt->fp_trail = (*pkt->fp_trail & 0xffff) | (fd->fd_status << 16);
1485 pkt->fp_hdr[0] = ((u_int32_t *)p)[1];
1486 pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
1487 #ifdef DIAGNOSTIC
1488 if (pkt->fp_tcode != IEEE1394_TCODE_STREAM_DATA) {
1489 printf("fwohci_buf_input_ppb: bad tcode: 0x%x\n",
1490 pkt->fp_tcode);
1491 return 0;
1492 }
1493 #endif
1494 pkt->fp_hlen = 4;
1495 pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
1496 p += 8;
1497 len -= 8;
1498 if (pkt->fp_dlen != len) {
1499 printf("fwohci_buf_input_ppb: malformed input 2: %d != %d\n",
1500 pkt->fp_dlen, len);
1501 return 0;
1502 }
1503 DPRINTFN(1, ("fwohci_buf_input_ppb: tcode=0x%x, hlen=%d, dlen=%d\n",
1504 pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
1505 pkt->fp_iov[0].iov_base = p;
1506 pkt->fp_iov[0].iov_len = len;
1507 pkt->fp_uio.uio_iovcnt = 0;
1508 pkt->fp_uio.uio_resid = len;
1509 return 1;
1510 }
1511
1512 static int
1513 fwohci_handler_set(struct fwohci_softc *sc,
1514 int tcode, u_int32_t key1, u_int32_t key2,
1515 int (*handler)(struct fwohci_softc *, void *, struct fwohci_pkt *),
1516 void *arg)
1517 {
1518 struct fwohci_ctx *fc;
1519 struct fwohci_handler *fh;
1520 int i, j;
1521
1522 if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1523 int isasync = key1 & OHCI_ASYNC_STREAM;
1524
1525 key1 &= IEEE1394_ISOCH_MASK;
1526 j = sc->sc_isoctx;
1527 fh = NULL;
1528 for (i = 0; i < sc->sc_isoctx; i++) {
1529 if ((fc = sc->sc_ctx_ir[i]) == NULL) {
1530 if (j == sc->sc_isoctx)
1531 j = i;
1532 continue;
1533 }
1534 fh = LIST_FIRST(&fc->fc_handler);
1535 if (fh->fh_tcode == tcode &&
1536 fh->fh_key1 == key1 && fh->fh_key2 == key2)
1537 break;
1538 fh = NULL;
1539 }
1540 if (fh == NULL) {
1541 if (handler == NULL)
1542 return 0;
1543 if (j == sc->sc_isoctx) {
1544 DPRINTF(("fwohci_handler_set: no more free "
1545 "context\n"));
1546 return ENOMEM;
1547 }
1548 if ((fc = sc->sc_ctx_ir[j]) == NULL) {
1549 fwohci_ctx_alloc(sc, &fc, OHCI_BUF_IR_CNT, j,
1550 isasync ? FWOHCI_CTX_ISO_SINGLE :
1551 FWOHCI_CTX_ISO_MULTI);
1552 sc->sc_ctx_ir[j] = fc;
1553 }
1554 }
1555 } else {
1556 switch (tcode) {
1557 case IEEE1394_TCODE_WRITE_REQ_QUAD:
1558 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1559 case IEEE1394_TCODE_READ_REQ_QUAD:
1560 case IEEE1394_TCODE_READ_REQ_BLOCK:
1561 case IEEE1394_TCODE_LOCK_REQ:
1562 fc = sc->sc_ctx_arrq;
1563 break;
1564 case IEEE1394_TCODE_WRITE_RESP:
1565 case IEEE1394_TCODE_READ_RESP_QUAD:
1566 case IEEE1394_TCODE_READ_RESP_BLOCK:
1567 case IEEE1394_TCODE_LOCK_RESP:
1568 fc = sc->sc_ctx_arrs;
1569 break;
1570 default:
1571 return EIO;
1572 }
1573 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1574 fh = LIST_NEXT(fh, fh_list)) {
1575 if (fh->fh_tcode == tcode &&
1576 fh->fh_key1 == key1 && fh->fh_key2 == key2)
1577 break;
1578 }
1579 }
1580 if (handler == NULL) {
1581 if (fh != NULL) {
1582 LIST_REMOVE(fh, fh_list);
1583 free(fh, M_DEVBUF);
1584 }
1585 if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1586 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1587 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1588 sc->sc_ctx_ir[fc->fc_ctx] = NULL;
1589 fwohci_ctx_free(sc, fc);
1590 }
1591 return 0;
1592 }
1593 if (fh == NULL) {
1594 fh = malloc(sizeof(*fh), M_DEVBUF, M_WAITOK);
1595 LIST_INSERT_HEAD(&fc->fc_handler, fh, fh_list);
1596 }
1597 fh->fh_tcode = tcode;
1598 fh->fh_key1 = key1;
1599 fh->fh_key2 = key2;
1600 fh->fh_handler = handler;
1601 fh->fh_handarg = arg;
1602 DPRINTFN(1, ("fwohci_handler_set: ctx %d, tcode %x, key 0x%x, 0x%x\n",
1603 fc->fc_ctx, tcode, key1, key2));
1604
1605 if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1606 fwohci_ctx_init(sc, fc);
1607 DPRINTFN(1, ("fwohci_handler_set: SYNC desc %ld\n",
1608 (long)(TAILQ_FIRST(&fc->fc_buf)->fb_desc - sc->sc_desc)));
1609 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1610 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1611 }
1612 return 0;
1613 }
1614
1615 /*
1616 * Asyncronous Receive Requests input frontend.
1617 */
1618 static void
1619 fwohci_arrq_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1620 {
1621 int rcode;
1622 u_int32_t key1, key2;
1623 struct fwohci_handler *fh;
1624 struct fwohci_pkt pkt, res;
1625
1626 /*
1627 * Do not return if next packet is in the buffer, or the next
1628 * packet cannot be received until the next receive interrupt.
1629 */
1630 while (fwohci_buf_input(sc, fc, &pkt)) {
1631 if (pkt.fp_tcode == OHCI_TCODE_PHY) {
1632 fwohci_phy_input(sc, &pkt);
1633 continue;
1634 }
1635 key1 = pkt.fp_hdr[1] & 0xffff;
1636 key2 = pkt.fp_hdr[2];
1637 memset(&res, 0, sizeof(res));
1638 res.fp_uio.uio_rw = UIO_WRITE;
1639 res.fp_uio.uio_segflg = UIO_SYSSPACE;
1640 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1641 fh = LIST_NEXT(fh, fh_list)) {
1642 if (pkt.fp_tcode == fh->fh_tcode &&
1643 key1 == fh->fh_key1 &&
1644 key2 == fh->fh_key2) {
1645 rcode = (*fh->fh_handler)(sc, fh->fh_handarg,
1646 &pkt);
1647 break;
1648 }
1649 }
1650 if (fh == NULL) {
1651 rcode = IEEE1394_RCODE_ADDRESS_ERROR;
1652 DPRINTFN(1, ("fwohci_arrq_input: no listener: tcode "
1653 "0x%x, addr=0x%04x %08x\n", pkt.fp_tcode, key1,
1654 key2));
1655 }
1656 if (((*pkt.fp_trail & 0x001f0000) >> 16) !=
1657 OHCI_CTXCTL_EVENT_ACK_PENDING)
1658 continue;
1659 if (rcode != -1)
1660 fwohci_atrs_output(sc, rcode, &pkt, &res);
1661 }
1662 fwohci_buf_next(sc, fc);
1663 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1664 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1665 }
1666
1667
1668 /*
1669 * Asynchronous Receive Response input frontend.
1670 */
1671 static void
1672 fwohci_arrs_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1673 {
1674 struct fwohci_pkt pkt;
1675 struct fwohci_handler *fh;
1676 u_int16_t srcid;
1677 int rcode, tlabel;
1678
1679 while (fwohci_buf_input(sc, fc, &pkt)) {
1680 srcid = pkt.fp_hdr[1] >> 16;
1681 rcode = (pkt.fp_hdr[1] & 0x0000f000) >> 12;
1682 tlabel = (pkt.fp_hdr[0] & 0x0000fc00) >> 10;
1683 DPRINTFN(1, ("fwohci_arrs_input: tcode 0x%x, from 0x%04x,"
1684 " tlabel 0x%x, rcode 0x%x, hlen %d, dlen %d\n",
1685 pkt.fp_tcode, srcid, tlabel, rcode, pkt.fp_hlen,
1686 pkt.fp_dlen));
1687 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1688 fh = LIST_NEXT(fh, fh_list)) {
1689 if (pkt.fp_tcode == fh->fh_tcode &&
1690 (srcid & OHCI_NodeId_NodeNumber) == fh->fh_key1 &&
1691 tlabel == fh->fh_key2) {
1692 (*fh->fh_handler)(sc, fh->fh_handarg, &pkt);
1693 LIST_REMOVE(fh, fh_list);
1694 free(fh, M_DEVBUF);
1695 break;
1696 }
1697 }
1698 if (fh == NULL)
1699 DPRINTFN(1, ("fwohci_arrs_input: no listner\n"));
1700 }
1701 fwohci_buf_next(sc, fc);
1702 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1703 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1704 }
1705
1706 /*
1707 * Isochronous Receive input frontend.
1708 */
1709 static void
1710 fwohci_ir_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1711 {
1712 int rcode, chan, tag;
1713 struct iovec *iov;
1714 struct fwohci_handler *fh;
1715 struct fwohci_pkt pkt;
1716
1717 #if DOUBLEBUF
1718 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) {
1719 struct fwohci_buf *fb;
1720 int i;
1721 u_int32_t reg;
1722
1723 /* stop dma engine before read buffer */
1724 reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx,
1725 OHCI_SUBREG_ContextControlClear);
1726 DPRINTFN(5, ("ir_input %08x =>", reg));
1727 if (reg & OHCI_CTXCTL_RUN) {
1728 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1729 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1730 }
1731 DPRINTFN(5, (" %08x\n", OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlClear)));
1732
1733 i = 0;
1734 while ((reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlSet)) & OHCI_CTXCTL_ACTIVE) {
1735 delay(10);
1736 if (++i > 10000) {
1737 printf("cannot stop dma engine 0x%08x\n", reg);
1738 return;
1739 }
1740 }
1741
1742 /* rotate dma buffer */
1743 fb = TAILQ_FIRST(&fc->fc_buf2);
1744 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_CommandPtr,
1745 fb->fb_daddr | 1);
1746 /* start dma engine */
1747 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1748 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1749 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear,
1750 (1 << fc->fc_ctx));
1751 }
1752 #endif
1753
1754 while (fwohci_buf_input_ppb(sc, fc, &pkt)) {
1755 chan = (pkt.fp_hdr[0] & 0x00003f00) >> 8;
1756 tag = (pkt.fp_hdr[0] & 0x0000c000) >> 14;
1757 DPRINTFN(1, ("fwohci_ir_input: hdr 0x%08x, tcode %d, hlen %d, "
1758 "dlen %d\n", pkt.fp_hdr[0], pkt.fp_tcode, pkt.fp_hlen,
1759 pkt.fp_dlen));
1760 if (tag == IEEE1394_TAG_GASP) {
1761 /*
1762 * The pkt with tag=3 is GASP format.
1763 * Move GASP header to header part.
1764 */
1765 if (pkt.fp_dlen < 8)
1766 continue;
1767 iov = pkt.fp_iov;
1768 /* assuming pkt per buffer mode */
1769 pkt.fp_hdr[1] = ntohl(((u_int32_t *)iov->iov_base)[0]);
1770 pkt.fp_hdr[2] = ntohl(((u_int32_t *)iov->iov_base)[1]);
1771 iov->iov_base = (caddr_t)iov->iov_base + 8;
1772 iov->iov_len -= 8;
1773 pkt.fp_hlen += 8;
1774 pkt.fp_dlen -= 8;
1775 }
1776 sc->sc_isopktcnt.ev_count++;
1777 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1778 fh = LIST_NEXT(fh, fh_list)) {
1779 if (pkt.fp_tcode == fh->fh_tcode &&
1780 chan == fh->fh_key1 && tag == fh->fh_key2) {
1781 rcode = (*fh->fh_handler)(sc, fh->fh_handarg,
1782 &pkt);
1783 break;
1784 }
1785 }
1786 #ifdef FW_DEBUG
1787 if (fh == NULL) {
1788 DPRINTFN(1, ("fwohci_ir_input: no handler\n"));
1789 } else {
1790 DPRINTFN(1, ("fwohci_ir_input: rcode %d\n", rcode));
1791 }
1792 #endif
1793 }
1794 fwohci_buf_next(sc, fc);
1795
1796 if (fc->fc_type == FWOHCI_CTX_ISO_SINGLE) {
1797 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1798 OHCI_SUBREG_ContextControlSet,
1799 OHCI_CTXCTL_WAKE);
1800 }
1801 }
1802
1803 /*
1804 * Asynchronous Transmit common routine.
1805 */
1806 static int
1807 fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1808 struct fwohci_pkt *pkt)
1809 {
1810 struct fwohci_buf *fb;
1811 struct fwohci_desc *fd;
1812 struct mbuf *m, *m0;
1813 int i, ndesc, error, off, len;
1814 u_int32_t val;
1815 #ifdef FW_DEBUG
1816 struct iovec *iov;
1817 #endif
1818
1819 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == IEEE1394_BCAST_PHY_ID)
1820 /* We can't send anything during selfid duration */
1821 return EAGAIN;
1822
1823 #ifdef FW_DEBUG
1824 DPRINTFN(1, ("fwohci_at_output: tcode 0x%x, hlen %d, dlen %d",
1825 pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
1826 for (i = 0; i < pkt->fp_hlen/4; i++)
1827 DPRINTFN(2, ("%s%08x", i?" ":"\n ", pkt->fp_hdr[i]));
1828 DPRINTFN(2, ("$"));
1829 for (ndesc = 0, iov = pkt->fp_iov;
1830 ndesc < pkt->fp_uio.uio_iovcnt; ndesc++, iov++) {
1831 for (i = 0; i < iov->iov_len; i++)
1832 DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n ",
1833 ((u_int8_t *)iov->iov_base)[i]));
1834 DPRINTFN(2, ("$"));
1835 }
1836 DPRINTFN(1, ("\n"));
1837 #endif
1838
1839 if ((m = pkt->fp_m) != NULL) {
1840 for (ndesc = 2; m != NULL; m = m->m_next)
1841 ndesc++;
1842 if (ndesc > OHCI_DESC_MAX) {
1843 m0 = NULL;
1844 ndesc = 2;
1845 for (off = 0; off < pkt->fp_dlen; off += len) {
1846 if (m0 == NULL) {
1847 MGETHDR(m0, M_DONTWAIT, MT_DATA);
1848 if (m0 != NULL)
1849 M_COPY_PKTHDR(m0, pkt->fp_m);
1850 m = m0;
1851 } else {
1852 MGET(m->m_next, M_DONTWAIT, MT_DATA);
1853 m = m->m_next;
1854 }
1855 if (m != NULL)
1856 MCLGET(m, M_DONTWAIT);
1857 if (m == NULL || (m->m_flags & M_EXT) == 0) {
1858 m_freem(m0);
1859 return ENOMEM;
1860 }
1861 len = pkt->fp_dlen - off;
1862 if (len > m->m_ext.ext_size)
1863 len = m->m_ext.ext_size;
1864 m_copydata(pkt->fp_m, off, len,
1865 mtod(m, caddr_t));
1866 m->m_len = len;
1867 ndesc++;
1868 }
1869 m_freem(pkt->fp_m);
1870 pkt->fp_m = m0;
1871 }
1872 } else
1873 ndesc = 2 + pkt->fp_uio.uio_iovcnt;
1874
1875 if (ndesc > OHCI_DESC_MAX)
1876 return ENOBUFS;
1877
1878 if (fc->fc_bufcnt > 50) /*XXX*/
1879 return ENOBUFS;
1880 fb = malloc(sizeof(*fb), M_DEVBUF, M_WAITOK);
1881 fb->fb_nseg = ndesc;
1882 fb->fb_desc = fwohci_desc_get(sc, ndesc);
1883 if (fb->fb_desc == NULL) {
1884 free(fb, M_DEVBUF);
1885 return ENOBUFS;
1886 }
1887 fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
1888 ((caddr_t)fb->fb_desc - (caddr_t)sc->sc_desc);
1889 fb->fb_m = pkt->fp_m;
1890 fb->fb_callback = pkt->fp_callback;
1891 fb->fb_statuscb = pkt->fp_statuscb;
1892 fb->fb_statusarg = pkt->fp_statusarg;
1893
1894 if (ndesc > 2) {
1895 if ((error = bus_dmamap_create(sc->sc_dmat, pkt->fp_dlen, ndesc,
1896 PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) {
1897 fwohci_desc_put(sc, fb->fb_desc, ndesc);
1898 free(fb, M_DEVBUF);
1899 return error;
1900 }
1901
1902 if (pkt->fp_m != NULL)
1903 error = bus_dmamap_load_mbuf(sc->sc_dmat, fb->fb_dmamap,
1904 pkt->fp_m, BUS_DMA_WAITOK);
1905 else
1906 error = bus_dmamap_load_uio(sc->sc_dmat, fb->fb_dmamap,
1907 &pkt->fp_uio, BUS_DMA_WAITOK);
1908 if (error != 0) {
1909 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1910 fwohci_desc_put(sc, fb->fb_desc, ndesc);
1911 free(fb, M_DEVBUF);
1912 return error;
1913 }
1914 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, pkt->fp_dlen,
1915 BUS_DMASYNC_PREWRITE);
1916 }
1917
1918 fd = fb->fb_desc;
1919 fd->fd_flags = OHCI_DESC_IMMED;
1920 fd->fd_reqcount = pkt->fp_hlen;
1921 fd->fd_data = 0;
1922 fd->fd_branch = 0;
1923 fd->fd_status = 0;
1924 if (fc->fc_ctx == OHCI_CTX_ASYNC_TX_RESPONSE) {
1925 i = 3; /* XXX: 3 sec */
1926 val = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
1927 fd->fd_timestamp = ((val >> 12) & 0x1fff) |
1928 ((((val >> 25) + i) & 0x7) << 13);
1929 } else
1930 fd->fd_timestamp = 0;
1931 memcpy(fd + 1, pkt->fp_hdr, pkt->fp_hlen);
1932 for (i = 0; i < ndesc - 2; i++) {
1933 fd = fb->fb_desc + 2 + i;
1934 fd->fd_flags = 0;
1935 fd->fd_reqcount = fb->fb_dmamap->dm_segs[i].ds_len;
1936 fd->fd_data = fb->fb_dmamap->dm_segs[i].ds_addr;
1937 fd->fd_branch = 0;
1938 fd->fd_status = 0;
1939 fd->fd_timestamp = 0;
1940 }
1941 fd->fd_flags |= OHCI_DESC_LAST | OHCI_DESC_BRANCH;
1942 fd->fd_flags |= OHCI_DESC_INTR_ALWAYS;
1943
1944 #ifdef FW_DEBUG
1945 DPRINTFN(1, ("fwohci_at_output: desc %ld",
1946 (long)(fb->fb_desc - sc->sc_desc)));
1947 for (i = 0; i < ndesc * 4; i++)
1948 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ",
1949 ((u_int32_t *)fb->fb_desc)[i]));
1950 DPRINTFN(1, ("\n"));
1951 #endif
1952
1953 val = OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
1954 OHCI_SUBREG_ContextControlClear);
1955
1956 if (val & OHCI_CTXCTL_RUN) {
1957 if (fc->fc_branch == NULL) {
1958 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1959 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1960 goto run;
1961 }
1962 *fc->fc_branch = fb->fb_daddr | ndesc;
1963 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1964 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1965 } else {
1966 run:
1967 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1968 OHCI_SUBREG_CommandPtr, fb->fb_daddr | ndesc);
1969 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1970 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1971 }
1972 fc->fc_branch = &fd->fd_branch;
1973
1974 fc->fc_bufcnt++;
1975 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
1976 pkt->fp_m = NULL;
1977 return 0;
1978 }
1979
1980 static void
1981 fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int force)
1982 {
1983 struct fwohci_buf *fb;
1984 struct fwohci_desc *fd;
1985 struct fwohci_pkt pkt;
1986 int i;
1987
1988 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1989 fd = fb->fb_desc;
1990 #ifdef FW_DEBUG
1991 DPRINTFN(1, ("fwohci_at_done: %sdesc %ld (%d)",
1992 force ? "force " : "", (long)(fd - sc->sc_desc),
1993 fb->fb_nseg));
1994 for (i = 0; i < fb->fb_nseg * 4; i++)
1995 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ",
1996 ((u_int32_t *)fd)[i]));
1997 DPRINTFN(1, ("\n"));
1998 #endif
1999 if (fb->fb_nseg > 2)
2000 fd += fb->fb_nseg - 1;
2001 if (!force && !(fd->fd_status & OHCI_CTXCTL_ACTIVE))
2002 break;
2003 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
2004 if (fc->fc_branch == &fd->fd_branch) {
2005 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
2006 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
2007 fc->fc_branch = NULL;
2008 for (i = 0; i < OHCI_LOOP; i++) {
2009 if (!(OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
2010 OHCI_SUBREG_ContextControlClear) &
2011 OHCI_CTXCTL_ACTIVE))
2012 break;
2013 DELAY(10);
2014 }
2015 }
2016
2017 if (fb->fb_statuscb) {
2018 memset(&pkt, 0, sizeof(pkt));
2019 pkt.fp_status = fd->fd_status;
2020 memcpy(pkt.fp_hdr, fd + 1, sizeof(pkt.fp_hdr[0]));
2021
2022 /* Indicate this is just returning the status bits. */
2023 pkt.fp_tcode = -1;
2024 (*fb->fb_statuscb)(sc, fb->fb_statusarg, &pkt);
2025 fb->fb_statuscb = NULL;
2026 fb->fb_statusarg = NULL;
2027 }
2028 fwohci_desc_put(sc, fb->fb_desc, fb->fb_nseg);
2029 if (fb->fb_nseg > 2)
2030 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
2031 fc->fc_bufcnt--;
2032 if (fb->fb_callback) {
2033 (*fb->fb_callback)(sc->sc_sc1394.sc1394_if, fb->fb_m);
2034 fb->fb_callback = NULL;
2035 } else if (fb->fb_m != NULL)
2036 m_freem(fb->fb_m);
2037 free(fb, M_DEVBUF);
2038 }
2039 }
2040
2041 /*
2042 * Asynchronous Transmit Reponse -- in response of request packet.
2043 */
2044 static void
2045 fwohci_atrs_output(struct fwohci_softc *sc, int rcode, struct fwohci_pkt *req,
2046 struct fwohci_pkt *res)
2047 {
2048
2049 if (((*req->fp_trail & 0x001f0000) >> 16) !=
2050 OHCI_CTXCTL_EVENT_ACK_PENDING)
2051 return;
2052
2053 res->fp_hdr[0] = (req->fp_hdr[0] & 0x0000fc00) | 0x00000100;
2054 res->fp_hdr[1] = (req->fp_hdr[1] & 0xffff0000) | (rcode << 12);
2055 switch (req->fp_tcode) {
2056 case IEEE1394_TCODE_WRITE_REQ_QUAD:
2057 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
2058 res->fp_tcode = IEEE1394_TCODE_WRITE_RESP;
2059 res->fp_hlen = 12;
2060 break;
2061 case IEEE1394_TCODE_READ_REQ_QUAD:
2062 res->fp_tcode = IEEE1394_TCODE_READ_RESP_QUAD;
2063 res->fp_hlen = 16;
2064 res->fp_dlen = 0;
2065 if (res->fp_uio.uio_iovcnt == 1 && res->fp_iov[0].iov_len == 4)
2066 res->fp_hdr[3] =
2067 *(u_int32_t *)res->fp_iov[0].iov_base;
2068 res->fp_uio.uio_iovcnt = 0;
2069 break;
2070 case IEEE1394_TCODE_READ_REQ_BLOCK:
2071 case IEEE1394_TCODE_LOCK_REQ:
2072 if (req->fp_tcode == IEEE1394_TCODE_LOCK_REQ)
2073 res->fp_tcode = IEEE1394_TCODE_LOCK_RESP;
2074 else
2075 res->fp_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
2076 res->fp_hlen = 16;
2077 res->fp_dlen = res->fp_uio.uio_resid;
2078 res->fp_hdr[3] = res->fp_dlen << 16;
2079 break;
2080 }
2081 res->fp_hdr[0] |= (res->fp_tcode << 4);
2082 fwohci_at_output(sc, sc->sc_ctx_atrs, res);
2083 }
2084
2085 /*
2086 * APPLICATION LAYER SERVICES
2087 */
2088
2089 /*
2090 * Retrieve Global UID from GUID ROM
2091 */
2092 static int
2093 fwohci_guidrom_init(struct fwohci_softc *sc)
2094 {
2095 int i, n, off;
2096 u_int32_t val1, val2;
2097
2098 /* Extract the Global UID
2099 */
2100 val1 = OHCI_CSR_READ(sc, OHCI_REG_GUIDHi);
2101 val2 = OHCI_CSR_READ(sc, OHCI_REG_GUIDLo);
2102
2103 if (val1 != 0 || val2 != 0) {
2104 sc->sc_sc1394.sc1394_guid[0] = (val1 >> 24) & 0xff;
2105 sc->sc_sc1394.sc1394_guid[1] = (val1 >> 16) & 0xff;
2106 sc->sc_sc1394.sc1394_guid[2] = (val1 >> 8) & 0xff;
2107 sc->sc_sc1394.sc1394_guid[3] = (val1 >> 0) & 0xff;
2108 sc->sc_sc1394.sc1394_guid[4] = (val2 >> 24) & 0xff;
2109 sc->sc_sc1394.sc1394_guid[5] = (val2 >> 16) & 0xff;
2110 sc->sc_sc1394.sc1394_guid[6] = (val2 >> 8) & 0xff;
2111 sc->sc_sc1394.sc1394_guid[7] = (val2 >> 0) & 0xff;
2112 } else {
2113 val1 = OHCI_CSR_READ(sc, OHCI_REG_Version);
2114 if ((val1 & OHCI_Version_GUID_ROM) == 0)
2115 return -1;
2116 OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom, OHCI_Guid_AddrReset);
2117 for (i = 0; i < OHCI_LOOP; i++) {
2118 val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
2119 if (!(val1 & OHCI_Guid_AddrReset))
2120 break;
2121 DELAY(10);
2122 }
2123 off = OHCI_BITVAL(val1, OHCI_Guid_MiniROM) + 4;
2124 val2 = 0;
2125 for (n = 0; n < off + sizeof(sc->sc_sc1394.sc1394_guid); n++) {
2126 OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom,
2127 OHCI_Guid_RdStart);
2128 for (i = 0; i < OHCI_LOOP; i++) {
2129 val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
2130 if (!(val1 & OHCI_Guid_RdStart))
2131 break;
2132 DELAY(10);
2133 }
2134 if (n < off)
2135 continue;
2136 val1 = OHCI_BITVAL(val1, OHCI_Guid_RdData);
2137 sc->sc_sc1394.sc1394_guid[n - off] = val1;
2138 val2 |= val1;
2139 }
2140 if (val2 == 0)
2141 return -1;
2142 }
2143 return 0;
2144 }
2145
2146 /*
2147 * Initialization for Configuration ROM (no DMA context)
2148 */
2149
2150 #define CFR_MAXUNIT 20
2151
2152 struct configromctx {
2153 u_int32_t *ptr;
2154 int curunit;
2155 struct {
2156 u_int32_t *start;
2157 int length;
2158 u_int32_t *refer;
2159 int refunit;
2160 } unit[CFR_MAXUNIT];
2161 };
2162
2163 #define CFR_PUT_DATA4(cfr, d1, d2, d3, d4) \
2164 (*(cfr)->ptr++ = (((d1)<<24) | ((d2)<<16) | ((d3)<<8) | (d4)))
2165
2166 #define CFR_PUT_DATA1(cfr, d) (*(cfr)->ptr++ = (d))
2167
2168 #define CFR_PUT_VALUE(cfr, key, d) (*(cfr)->ptr++ = ((key)<<24) | (d))
2169
2170 #define CFR_PUT_CRC(cfr, n) \
2171 (*(cfr)->unit[n].start = ((cfr)->unit[n].length << 16) | \
2172 fwohci_crc16((cfr)->unit[n].start + 1, (cfr)->unit[n].length))
2173
2174 #define CFR_START_UNIT(cfr, n) \
2175 do { \
2176 if ((cfr)->unit[n].refer != NULL) { \
2177 *(cfr)->unit[n].refer |= \
2178 (cfr)->ptr - (cfr)->unit[n].refer; \
2179 CFR_PUT_CRC(cfr, (cfr)->unit[n].refunit); \
2180 } \
2181 (cfr)->curunit = (n); \
2182 (cfr)->unit[n].start = (cfr)->ptr++; \
2183 } while (0 /* CONSTCOND */)
2184
2185 #define CFR_PUT_REFER(cfr, key, n) \
2186 do { \
2187 (cfr)->unit[n].refer = (cfr)->ptr; \
2188 (cfr)->unit[n].refunit = (cfr)->curunit; \
2189 *(cfr)->ptr++ = (key) << 24; \
2190 } while (0 /* CONSTCOND */)
2191
2192 #define CFR_END_UNIT(cfr) \
2193 do { \
2194 (cfr)->unit[(cfr)->curunit].length = (cfr)->ptr - \
2195 ((cfr)->unit[(cfr)->curunit].start + 1); \
2196 CFR_PUT_CRC(cfr, (cfr)->curunit); \
2197 } while (0 /* CONSTCOND */)
2198
2199 static u_int16_t
2200 fwohci_crc16(u_int32_t *ptr, int len)
2201 {
2202 int shift;
2203 u_int32_t crc, sum, data;
2204
2205 crc = 0;
2206 while (len-- > 0) {
2207 data = *ptr++;
2208 for (shift = 28; shift >= 0; shift -= 4) {
2209 sum = ((crc >> 12) ^ (data >> shift)) & 0x000f;
2210 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
2211 }
2212 crc &= 0xffff;
2213 }
2214 return crc;
2215 }
2216
2217 static void
2218 fwohci_configrom_init(struct fwohci_softc *sc)
2219 {
2220 int i, val;
2221 struct fwohci_buf *fb;
2222 u_int32_t *hdr;
2223 struct configromctx cfr;
2224
2225 fb = &sc->sc_buf_cnfrom;
2226 memset(&cfr, 0, sizeof(cfr));
2227 cfr.ptr = hdr = (u_int32_t *)fb->fb_buf;
2228
2229 /* headers */
2230 CFR_START_UNIT(&cfr, 0);
2231 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusId));
2232 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusOptions));
2233 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDHi));
2234 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDLo));
2235 CFR_END_UNIT(&cfr);
2236 /* copy info_length from crc_length */
2237 *hdr |= (*hdr & 0x00ff0000) << 8;
2238 OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMhdr, *hdr);
2239
2240 /* root directory */
2241 CFR_START_UNIT(&cfr, 1);
2242 CFR_PUT_VALUE(&cfr, 0x03, 0x00005e); /* vendor id */
2243 CFR_PUT_REFER(&cfr, 0x81, 2); /* textual descriptor offset */
2244 CFR_PUT_VALUE(&cfr, 0x0c, 0x0083c0); /* node capability */
2245 /* spt,64,fix,lst,drq */
2246 #ifdef INET
2247 CFR_PUT_REFER(&cfr, 0xd1, 3); /* IPv4 unit directory */
2248 #endif /* INET */
2249 #ifdef INET6
2250 CFR_PUT_REFER(&cfr, 0xd1, 4); /* IPv6 unit directory */
2251 #endif /* INET6 */
2252 CFR_END_UNIT(&cfr);
2253
2254 CFR_START_UNIT(&cfr, 2);
2255 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
2256 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
2257 CFR_PUT_DATA4(&cfr, 'N', 'e', 't', 'B');
2258 CFR_PUT_DATA4(&cfr, 'S', 'D', 0x00, 0x00);
2259 CFR_END_UNIT(&cfr);
2260
2261 #ifdef INET
2262 /* IPv4 unit directory */
2263 CFR_START_UNIT(&cfr, 3);
2264 CFR_PUT_VALUE(&cfr, 0x12, 0x00005e); /* unit spec id */
2265 CFR_PUT_REFER(&cfr, 0x81, 6); /* textual descriptor offset */
2266 CFR_PUT_VALUE(&cfr, 0x13, 0x000001); /* unit sw version */
2267 CFR_PUT_REFER(&cfr, 0x81, 7); /* textual descriptor offset */
2268 CFR_END_UNIT(&cfr);
2269
2270 CFR_START_UNIT(&cfr, 6);
2271 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
2272 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
2273 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
2274 CFR_END_UNIT(&cfr);
2275
2276 CFR_START_UNIT(&cfr, 7);
2277 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
2278 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
2279 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '4');
2280 CFR_END_UNIT(&cfr);
2281 #endif /* INET */
2282
2283 #ifdef INET6
2284 /* IPv6 unit directory */
2285 CFR_START_UNIT(&cfr, 4);
2286 CFR_PUT_VALUE(&cfr, 0x12, 0x00005e); /* unit spec id */
2287 CFR_PUT_REFER(&cfr, 0x81, 8); /* textual descriptor offset */
2288 CFR_PUT_VALUE(&cfr, 0x13, 0x000002); /* unit sw version */
2289 /* XXX: TBA by IANA */
2290 CFR_PUT_REFER(&cfr, 0x81, 9); /* textual descriptor offset */
2291 CFR_END_UNIT(&cfr);
2292
2293 CFR_START_UNIT(&cfr, 8);
2294 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
2295 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
2296 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
2297 CFR_END_UNIT(&cfr);
2298
2299 CFR_START_UNIT(&cfr, 9);
2300 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
2301 CFR_PUT_DATA1(&cfr, 0);
2302 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '6');
2303 CFR_END_UNIT(&cfr);
2304 #endif /* INET6 */
2305
2306 fb->fb_off = cfr.ptr - hdr;
2307 #ifdef FW_DEBUG
2308 DPRINTFN(2, ("%s: Config ROM:", sc->sc_sc1394.sc1394_dev.dv_xname));
2309 for (i = 0; i < fb->fb_off; i++)
2310 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ", hdr[i]));
2311 DPRINTFN(2, ("\n"));
2312 #endif /* FW_DEBUG */
2313
2314 /*
2315 * Make network byte order for DMA
2316 */
2317 for (i = 0; i < fb->fb_off; i++)
2318 HTONL(hdr[i]);
2319 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
2320 (caddr_t)cfr.ptr - fb->fb_buf, BUS_DMASYNC_PREWRITE);
2321
2322 OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMmap,
2323 fb->fb_dmamap->dm_segs[0].ds_addr);
2324
2325 /* This register is only valid on OHCI 1.1. */
2326 val = OHCI_CSR_READ(sc, OHCI_REG_Version);
2327 if ((OHCI_Version_GET_Version(val) == 1) &&
2328 (OHCI_Version_GET_Revision(val) == 1))
2329 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet,
2330 OHCI_HCControl_BIBImageValid);
2331
2332 /* Just allow quad reads of the rom. */
2333 for (i = 0; i < fb->fb_off; i++)
2334 fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD,
2335 CSR_BASE_HI, CSR_BASE_LO + CSR_CONFIG_ROM + (i * 4),
2336 fwohci_configrom_input, NULL);
2337 }
2338
2339 static int
2340 fwohci_configrom_input(struct fwohci_softc *sc, void *arg,
2341 struct fwohci_pkt *pkt)
2342 {
2343 struct fwohci_pkt res;
2344 u_int32_t loc, *rom;
2345
2346 /* This will be used as an array index so size accordingly. */
2347 loc = pkt->fp_hdr[2] - (CSR_BASE_LO + CSR_CONFIG_ROM);
2348 if ((loc & 0x03) != 0) {
2349 /* alignment error */
2350 return IEEE1394_RCODE_ADDRESS_ERROR;
2351 }
2352 else
2353 loc /= 4;
2354 rom = (u_int32_t *)sc->sc_buf_cnfrom.fb_buf;
2355
2356 DPRINTFN(1, ("fwohci_configrom_input: ConfigRom[0x%04x]: 0x%08x\n", loc,
2357 ntohl(rom[loc])));
2358
2359 memset(&res, 0, sizeof(res));
2360 res.fp_hdr[3] = rom[loc];
2361 fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res);
2362 return -1;
2363 }
2364
2365 /*
2366 * SelfID buffer (no DMA context)
2367 */
2368 static void
2369 fwohci_selfid_init(struct fwohci_softc *sc)
2370 {
2371 struct fwohci_buf *fb;
2372
2373 fb = &sc->sc_buf_selfid;
2374 #ifdef DIAGNOSTIC
2375 if ((fb->fb_dmamap->dm_segs[0].ds_addr & 0x7ff) != 0)
2376 panic("fwohci_selfid_init: not aligned: %p (%ld) %p",
2377 (caddr_t)fb->fb_dmamap->dm_segs[0].ds_addr,
2378 (unsigned long)fb->fb_dmamap->dm_segs[0].ds_len, fb->fb_buf);
2379 #endif
2380 memset(fb->fb_buf, 0, fb->fb_dmamap->dm_segs[0].ds_len);
2381 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
2382 fb->fb_dmamap->dm_segs[0].ds_len, BUS_DMASYNC_PREREAD);
2383
2384 OHCI_CSR_WRITE(sc, OHCI_REG_SelfIDBuffer,
2385 fb->fb_dmamap->dm_segs[0].ds_addr);
2386 }
2387
2388 static int
2389 fwohci_selfid_input(struct fwohci_softc *sc)
2390 {
2391 int i;
2392 u_int32_t count, val, gen;
2393 u_int32_t *buf;
2394
2395 buf = (u_int32_t *)sc->sc_buf_selfid.fb_buf;
2396 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
2397 again:
2398 if (val & OHCI_SelfID_Error) {
2399 printf("%s: SelfID Error\n", sc->sc_sc1394.sc1394_dev.dv_xname);
2400 return -1;
2401 }
2402 count = OHCI_BITVAL(val, OHCI_SelfID_Size);
2403
2404 bus_dmamap_sync(sc->sc_dmat, sc->sc_buf_selfid.fb_dmamap,
2405 0, count << 2, BUS_DMASYNC_POSTREAD);
2406 gen = OHCI_BITVAL(buf[0], OHCI_SelfID_Gen);
2407
2408 #ifdef FW_DEBUG
2409 DPRINTFN(1, ("%s: SelfID: 0x%08x", sc->sc_sc1394.sc1394_dev.dv_xname,
2410 val));
2411 for (i = 0; i < count; i++)
2412 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ", buf[i]));
2413 DPRINTFN(1, ("\n"));
2414 #endif /* FW_DEBUG */
2415
2416 for (i = 1; i < count; i += 2) {
2417 if (buf[i] != ~buf[i + 1])
2418 break;
2419 if (buf[i] & 0x00000001)
2420 continue; /* more pkt */
2421 if (buf[i] & 0x00800000)
2422 continue; /* external id */
2423 sc->sc_rootid = (buf[i] & 0x3f000000) >> 24;
2424 if ((buf[i] & 0x00400800) == 0x00400800)
2425 sc->sc_irmid = sc->sc_rootid;
2426 }
2427
2428 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
2429 if (OHCI_BITVAL(val, OHCI_SelfID_Gen) != gen) {
2430 if (OHCI_BITVAL(val, OHCI_SelfID_Gen) !=
2431 OHCI_BITVAL(buf[0], OHCI_SelfID_Gen))
2432 goto again;
2433 DPRINTF(("%s: SelfID Gen mismatch (%d, %d)\n",
2434 sc->sc_sc1394.sc1394_dev.dv_xname, gen,
2435 OHCI_BITVAL(val, OHCI_SelfID_Gen)));
2436 return -1;
2437 }
2438 if (i != count) {
2439 printf("%s: SelfID corrupted (%d, 0x%08x, 0x%08x)\n",
2440 sc->sc_sc1394.sc1394_dev.dv_xname, i, buf[i], buf[i + 1]);
2441 #if 1
2442 if (i == 1 && buf[i] == 0 && buf[i + 1] == 0) {
2443 /*
2444 * XXX: CXD3222 sometimes fails to DMA
2445 * selfid packet??
2446 */
2447 sc->sc_rootid = (count - 1) / 2 - 1;
2448 sc->sc_irmid = sc->sc_rootid;
2449 } else
2450 #endif
2451 return -1;
2452 }
2453
2454 val = OHCI_CSR_READ(sc, OHCI_REG_NodeId);
2455 if ((val & OHCI_NodeId_IDValid) == 0) {
2456 sc->sc_nodeid = 0xffff; /* invalid */
2457 printf("%s: nodeid is invalid\n",
2458 sc->sc_sc1394.sc1394_dev.dv_xname);
2459 return -1;
2460 }
2461 sc->sc_nodeid = val & 0xffff;
2462
2463 DPRINTF(("%s: nodeid=0x%04x(%d), rootid=%d, irmid=%d\n",
2464 sc->sc_sc1394.sc1394_dev.dv_xname, sc->sc_nodeid,
2465 sc->sc_nodeid & OHCI_NodeId_NodeNumber, sc->sc_rootid,
2466 sc->sc_irmid));
2467
2468 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid)
2469 return -1;
2470
2471 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == sc->sc_rootid)
2472 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet,
2473 OHCI_LinkControl_CycleMaster);
2474 else
2475 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear,
2476 OHCI_LinkControl_CycleMaster);
2477 return 0;
2478 }
2479
2480 /*
2481 * some CSRs are handled by driver.
2482 */
2483 static void
2484 fwohci_csr_init(struct fwohci_softc *sc)
2485 {
2486 int i;
2487 static u_int32_t csr[] = {
2488 CSR_STATE_CLEAR, CSR_STATE_SET, CSR_SB_CYCLE_TIME,
2489 CSR_SB_BUS_TIME, CSR_SB_BUSY_TIMEOUT, CSR_SB_BUS_MANAGER_ID,
2490 CSR_SB_CHANNEL_AVAILABLE_HI, CSR_SB_CHANNEL_AVAILABLE_LO,
2491 CSR_SB_BROADCAST_CHANNEL
2492 };
2493
2494 for (i = 0; i < sizeof(csr) / sizeof(csr[0]); i++) {
2495 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_QUAD,
2496 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL);
2497 fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD,
2498 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL);
2499 }
2500 sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] = 31; /*XXX*/
2501 }
2502
2503 static int
2504 fwohci_csr_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2505 {
2506 struct fwohci_pkt res;
2507 u_int32_t reg;
2508
2509 /*
2510 * XXX need to do special functionality other than just r/w...
2511 */
2512 reg = pkt->fp_hdr[2] - CSR_BASE_LO;
2513
2514 if ((reg & 0x03) != 0) {
2515 /* alignment error */
2516 return IEEE1394_RCODE_ADDRESS_ERROR;
2517 }
2518 DPRINTFN(1, ("fwohci_csr_input: CSR[0x%04x]: 0x%08x", reg,
2519 *(u_int32_t *)(&sc->sc_csr[reg])));
2520 if (pkt->fp_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) {
2521 DPRINTFN(1, (" -> 0x%08x\n",
2522 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base)));
2523 *(u_int32_t *)&sc->sc_csr[reg] =
2524 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base);
2525 } else {
2526 DPRINTFN(1, ("\n"));
2527 res.fp_hdr[3] = htonl(*(u_int32_t *)&sc->sc_csr[reg]);
2528 res.fp_iov[0].iov_base = &res.fp_hdr[3];
2529 res.fp_iov[0].iov_len = 4;
2530 res.fp_uio.uio_resid = 4;
2531 res.fp_uio.uio_iovcnt = 1;
2532 fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res);
2533 return -1;
2534 }
2535 return IEEE1394_RCODE_COMPLETE;
2536 }
2537
2538 /*
2539 * Mapping between nodeid and unique ID (EUI-64).
2540 *
2541 * Track old mappings and simply update their devices with the new id's when
2542 * they match an existing EUI. This allows proper renumeration of the bus.
2543 */
2544 static void
2545 fwohci_uid_collect(struct fwohci_softc *sc)
2546 {
2547 int i;
2548 struct fwohci_uidtbl *fu;
2549 struct ieee1394_softc *iea;
2550
2551 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node)
2552 iea->sc1394_node_id = 0xffff;
2553
2554 if (sc->sc_uidtbl != NULL)
2555 free(sc->sc_uidtbl, M_DEVBUF);
2556 sc->sc_uidtbl = malloc(sizeof(*fu) * (sc->sc_rootid + 1), M_DEVBUF,
2557 M_NOWAIT); /* XXX M_WAITOK requires locks */
2558 if (sc->sc_uidtbl == NULL)
2559 return;
2560 memset(sc->sc_uidtbl, 0, sizeof(*fu) * (sc->sc_rootid + 1));
2561
2562 for (i = 0, fu = sc->sc_uidtbl; i <= sc->sc_rootid; i++, fu++) {
2563 if (i == (sc->sc_nodeid & OHCI_NodeId_NodeNumber)) {
2564 memcpy(fu->fu_uid, sc->sc_sc1394.sc1394_guid, 8);
2565 fu->fu_valid = 3;
2566
2567 iea = (struct ieee1394_softc *)sc->sc_sc1394.sc1394_if;
2568 if (iea) {
2569 iea->sc1394_node_id = i;
2570 DPRINTF(("%s: Updating nodeid to %d\n",
2571 iea->sc1394_dev.dv_xname,
2572 iea->sc1394_node_id));
2573 }
2574 } else {
2575 fu->fu_valid = 0;
2576 fwohci_uid_req(sc, i);
2577 }
2578 }
2579 if (sc->sc_rootid == 0)
2580 fwohci_check_nodes(sc);
2581 }
2582
2583 static void
2584 fwohci_uid_req(struct fwohci_softc *sc, int phyid)
2585 {
2586 struct fwohci_pkt pkt;
2587
2588 memset(&pkt, 0, sizeof(pkt));
2589 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
2590 pkt.fp_hlen = 12;
2591 pkt.fp_dlen = 0;
2592 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
2593 (pkt.fp_tcode << 4);
2594 pkt.fp_hdr[1] = ((0xffc0 | phyid) << 16) | CSR_BASE_HI;
2595 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12;
2596 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
2597 sc->sc_tlabel, fwohci_uid_input, (void *)0);
2598 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
2599 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
2600
2601 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
2602 (pkt.fp_tcode << 4);
2603 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16;
2604 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
2605 sc->sc_tlabel, fwohci_uid_input, (void *)1);
2606 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
2607 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
2608 }
2609
2610 static int
2611 fwohci_uid_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *res)
2612 {
2613 struct fwohci_uidtbl *fu;
2614 struct ieee1394_softc *iea;
2615 struct ieee1394_attach_args fwa;
2616 int i, n, done, rcode, found;
2617
2618 found = 0;
2619
2620 n = (res->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2621 rcode = (res->fp_hdr[1] & 0x0000f000) >> 12;
2622 if (rcode != IEEE1394_RCODE_COMPLETE ||
2623 sc->sc_uidtbl == NULL ||
2624 n > sc->sc_rootid)
2625 return 0;
2626 fu = &sc->sc_uidtbl[n];
2627 if (arg == 0) {
2628 memcpy(fu->fu_uid, res->fp_iov[0].iov_base, 4);
2629 fu->fu_valid |= 0x1;
2630 } else {
2631 memcpy(fu->fu_uid + 4, res->fp_iov[0].iov_base, 4);
2632 fu->fu_valid |= 0x2;
2633 }
2634 #ifdef FW_DEBUG
2635 if (fu->fu_valid == 0x3)
2636 DPRINTFN(1, ("fwohci_uid_input: "
2637 "Node %d, UID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", n,
2638 fu->fu_uid[0], fu->fu_uid[1], fu->fu_uid[2], fu->fu_uid[3],
2639 fu->fu_uid[4], fu->fu_uid[5], fu->fu_uid[6], fu->fu_uid[7]));
2640 #endif
2641 if (fu->fu_valid == 0x3) {
2642 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node)
2643 if (memcmp(iea->sc1394_guid, fu->fu_uid, 8) == 0) {
2644 found = 1;
2645 iea->sc1394_node_id = n;
2646 DPRINTF(("%s: Updating nodeid to %d\n",
2647 iea->sc1394_dev.dv_xname,
2648 iea->sc1394_node_id));
2649 break;
2650 }
2651 if (!found) {
2652 strcpy(fwa.name, "fwnode");
2653 memcpy(fwa.uid, fu->fu_uid, 8);
2654 fwa.nodeid = n;
2655 fwa.read = fwohci_read;
2656 fwa.write = fwohci_write;
2657 fwa.inreg = fwohci_inreg;
2658 iea = (struct ieee1394_softc *)
2659 config_found_sm(&sc->sc_sc1394.sc1394_dev, &fwa,
2660 fwohci_print, fwohci_submatch);
2661 if (iea != NULL)
2662 LIST_INSERT_HEAD(&sc->sc_nodelist, iea,
2663 sc1394_node);
2664 }
2665 }
2666 done = 1;
2667
2668 for (i = 0; i < sc->sc_rootid + 1; i++) {
2669 fu = &sc->sc_uidtbl[i];
2670 if (fu->fu_valid != 0x3) {
2671 done = 0;
2672 break;
2673 }
2674 }
2675 if (done)
2676 fwohci_check_nodes(sc);
2677
2678 return 0;
2679 }
2680
2681 static void
2682 fwohci_check_nodes(struct fwohci_softc *sc)
2683 {
2684 struct device *detach = NULL;
2685 struct ieee1394_softc *iea;
2686
2687 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) {
2688
2689 /*
2690 * Have to defer detachment until the next
2691 * loop iteration since config_detach
2692 * free's the softc and the loop iterator
2693 * needs data from the softc to move
2694 * forward.
2695 */
2696
2697 if (detach) {
2698 config_detach(detach, 0);
2699 detach = NULL;
2700 }
2701 if (iea->sc1394_node_id == 0xffff) {
2702 detach = (struct device *)iea;
2703 LIST_REMOVE(iea, sc1394_node);
2704 }
2705 }
2706 if (detach)
2707 config_detach(detach, 0);
2708 }
2709
2710 static int
2711 fwohci_uid_lookup(struct fwohci_softc *sc, const u_int8_t *uid)
2712 {
2713 struct fwohci_uidtbl *fu;
2714 int n;
2715 static const u_int8_t bcast[] =
2716 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2717
2718 fu = sc->sc_uidtbl;
2719 if (fu == NULL) {
2720 if (memcmp(uid, bcast, sizeof(bcast)) == 0)
2721 return IEEE1394_BCAST_PHY_ID;
2722 fwohci_uid_collect(sc); /* try to get */
2723 return -1;
2724 }
2725 for (n = 0; n <= sc->sc_rootid; n++, fu++) {
2726 if (fu->fu_valid == 0x3 && memcmp(fu->fu_uid, uid, 8) == 0)
2727 return n;
2728 }
2729 if (memcmp(uid, bcast, sizeof(bcast)) == 0)
2730 return IEEE1394_BCAST_PHY_ID;
2731 for (n = 0, fu = sc->sc_uidtbl; n <= sc->sc_rootid; n++, fu++) {
2732 if (fu->fu_valid != 0x3) {
2733 /*
2734 * XXX: need timer before retransmission
2735 */
2736 fwohci_uid_req(sc, n);
2737 }
2738 }
2739 return -1;
2740 }
2741
2742 /*
2743 * functions to support network interface
2744 */
2745 static int
2746 fwohci_if_inreg(struct device *self, u_int32_t offhi, u_int32_t offlo,
2747 void (*handler)(struct device *, struct mbuf *))
2748 {
2749 struct fwohci_softc *sc = (struct fwohci_softc *)self;
2750
2751 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_BLOCK, offhi, offlo,
2752 handler ? fwohci_if_input : NULL, handler);
2753 fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA,
2754 (sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & IEEE1394_ISOCH_MASK) | OHCI_ASYNC_STREAM,
2755 IEEE1394_TAG_GASP, handler ? fwohci_if_input : NULL, handler);
2756 return 0;
2757 }
2758
2759 static int
2760 fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2761 {
2762 int n, len;
2763 struct mbuf *m;
2764 struct iovec *iov;
2765 void (*handler)(struct device *, struct mbuf *) = arg;
2766
2767 #ifdef FW_DEBUG
2768 int i;
2769 DPRINTFN(1, ("fwohci_if_input: tcode=0x%x, dlen=%d", pkt->fp_tcode,
2770 pkt->fp_dlen));
2771 for (i = 0; i < pkt->fp_hlen/4; i++)
2772 DPRINTFN(2, ("%s%08x", i?" ":"\n ", pkt->fp_hdr[i]));
2773 DPRINTFN(2, ("$"));
2774 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
2775 iov = &pkt->fp_iov[n];
2776 for (i = 0; i < iov->iov_len; i++)
2777 DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n ",
2778 ((u_int8_t *)iov->iov_base)[i]));
2779 DPRINTFN(2, ("$"));
2780 }
2781 DPRINTFN(1, ("\n"));
2782 #endif /* FW_DEBUG */
2783 len = pkt->fp_dlen;
2784 MGETHDR(m, M_DONTWAIT, MT_DATA);
2785 if (m == NULL)
2786 return IEEE1394_RCODE_COMPLETE;
2787 m->m_len = 16;
2788 if (len + m->m_len > MHLEN) {
2789 MCLGET(m, M_DONTWAIT);
2790 if ((m->m_flags & M_EXT) == 0) {
2791 m_freem(m);
2792 return IEEE1394_RCODE_COMPLETE;
2793 }
2794 }
2795 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2796 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
2797 sc->sc_uidtbl[n].fu_valid != 0x3) {
2798 printf("%s: packet from unknown node: phy id %d\n",
2799 sc->sc_sc1394.sc1394_dev.dv_xname, n);
2800 m_freem(m);
2801 fwohci_uid_req(sc, n);
2802 return IEEE1394_RCODE_COMPLETE;
2803 }
2804 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
2805 if (pkt->fp_tcode == IEEE1394_TCODE_STREAM_DATA) {
2806 m->m_flags |= M_BCAST;
2807 mtod(m, u_int32_t *)[2] = mtod(m, u_int32_t *)[3] = 0;
2808 } else {
2809 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
2810 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
2811 }
2812 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */
2813 mtod(m, u_int8_t *)[9] =
2814 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
2815 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
2816
2817 m->m_pkthdr.rcvif = NULL; /* set in child */
2818 m->m_pkthdr.len = len + m->m_len;
2819 /*
2820 * We may use receive buffer by external mbuf instead of copy here.
2821 * But asynchronous receive buffer must be operate in buffer fill
2822 * mode, so that each receive buffer will shared by multiple mbufs.
2823 * If upper layer doesn't free mbuf soon, e.g. application program
2824 * is suspended, buffer must be reallocated.
2825 * Isochronous buffer must be operate in packet buffer mode, and
2826 * it is easy to map receive buffer to external mbuf. But it is
2827 * used for broadcast/multicast only, and is expected not so
2828 * performance sensitive for now.
2829 * XXX: The performance may be important for multicast case,
2830 * so we should revisit here later.
2831 * -- onoe
2832 */
2833 n = 0;
2834 iov = pkt->fp_uio.uio_iov;
2835 while (len > 0) {
2836 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
2837 iov->iov_len);
2838 m->m_len += iov->iov_len;
2839 len -= iov->iov_len;
2840 iov++;
2841 }
2842 (*handler)(sc->sc_sc1394.sc1394_if, m);
2843 return IEEE1394_RCODE_COMPLETE;
2844 }
2845
2846 static int
2847 fwohci_if_input_iso(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2848 {
2849 int n, len;
2850 int chan, tag;
2851 struct mbuf *m;
2852 struct iovec *iov;
2853 void (*handler)(struct device *, struct mbuf *) = arg;
2854 #ifdef FW_DEBUG
2855 int i;
2856 #endif
2857
2858 chan = (pkt->fp_hdr[0] & 0x00003f00) >> 8;
2859 tag = (pkt->fp_hdr[0] & 0x0000c000) >> 14;
2860 #ifdef FW_DEBUG
2861 DPRINTFN(1, ("fwohci_if_input_iso: "
2862 "tcode=0x%x, chan=%d, tag=%x, dlen=%d",
2863 pkt->fp_tcode, chan, tag, pkt->fp_dlen));
2864 for (i = 0; i < pkt->fp_hlen/4; i++)
2865 DPRINTFN(2, ("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i]));
2866 DPRINTFN(2, ("$"));
2867 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
2868 iov = &pkt->fp_iov[n];
2869 for (i = 0; i < iov->iov_len; i++)
2870 DPRINTFN(2, ("%s%02x",
2871 (i%32)?((i%4)?"":" "):"\n\t",
2872 ((u_int8_t *)iov->iov_base)[i]));
2873 DPRINTFN(2, ("$"));
2874 }
2875 DPRINTFN(2, ("\n"));
2876 #endif /* FW_DEBUG */
2877 len = pkt->fp_dlen;
2878 MGETHDR(m, M_DONTWAIT, MT_DATA);
2879 if (m == NULL)
2880 return IEEE1394_RCODE_COMPLETE;
2881 m->m_len = 16;
2882 if (m->m_len + len > MHLEN) {
2883 MCLGET(m, M_DONTWAIT);
2884 if ((m->m_flags & M_EXT) == 0) {
2885 m_freem(m);
2886 return IEEE1394_RCODE_COMPLETE;
2887 }
2888 }
2889
2890 m->m_flags |= M_BCAST;
2891
2892 if (tag == IEEE1394_TAG_GASP) {
2893 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2894 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
2895 sc->sc_uidtbl[n].fu_valid != 0x3) {
2896 printf("%s: packet from unknown node: phy id %d\n",
2897 sc->sc_sc1394.sc1394_dev.dv_xname, n);
2898 m_freem(m);
2899 return IEEE1394_RCODE_COMPLETE;
2900 }
2901 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
2902 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
2903 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
2904 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */
2905 mtod(m, u_int8_t *)[9] =
2906 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
2907 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
2908 } else {
2909 m->m_flags |= M_LINK0;
2910 }
2911 mtod(m, u_int8_t *)[14] = chan;
2912 mtod(m, u_int8_t *)[15] = tag;
2913
2914
2915 m->m_pkthdr.rcvif = NULL; /* set in child */
2916 m->m_pkthdr.len = len + m->m_len;
2917 /*
2918 * We may use receive buffer by external mbuf instead of copy here.
2919 * But asynchronous receive buffer must be operate in buffer fill
2920 * mode, so that each receive buffer will shared by multiple mbufs.
2921 * If upper layer doesn't free mbuf soon, e.g. application program
2922 * is suspended, buffer must be reallocated.
2923 * Isochronous buffer must be operate in packet buffer mode, and
2924 * it is easy to map receive buffer to external mbuf. But it is
2925 * used for broadcast/multicast only, and is expected not so
2926 * performance sensitive for now.
2927 * XXX: The performance may be important for multicast case,
2928 * so we should revisit here later.
2929 * -- onoe
2930 */
2931 n = 0;
2932 iov = pkt->fp_uio.uio_iov;
2933 while (len > 0) {
2934 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
2935 iov->iov_len);
2936 m->m_len += iov->iov_len;
2937 len -= iov->iov_len;
2938 iov++;
2939 }
2940 (*handler)(sc->sc_sc1394.sc1394_if, m);
2941 return IEEE1394_RCODE_COMPLETE;
2942 }
2943
2944
2945
2946 static int
2947 fwohci_if_output(struct device *self, struct mbuf *m0,
2948 void (*callback)(struct device *, struct mbuf *))
2949 {
2950 struct fwohci_softc *sc = (struct fwohci_softc *)self;
2951 struct fwohci_pkt pkt;
2952 u_int8_t *p;
2953 int n, error, spd, hdrlen, maxrec;
2954 #ifdef FW_DEBUG
2955 struct mbuf *m;
2956 #endif
2957
2958 p = mtod(m0, u_int8_t *);
2959 if (m0->m_flags & (M_BCAST | M_MCAST)) {
2960 spd = IEEE1394_SPD_S100; /*XXX*/
2961 maxrec = 512; /*XXX*/
2962 hdrlen = 8;
2963 } else {
2964 n = fwohci_uid_lookup(sc, p);
2965 if (n < 0) {
2966 printf("%s: nodeid unknown:"
2967 " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
2968 sc->sc_sc1394.sc1394_dev.dv_xname,
2969 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
2970 error = EHOSTUNREACH;
2971 goto end;
2972 }
2973 if (n == IEEE1394_BCAST_PHY_ID) {
2974 printf("%s: broadcast with !M_MCAST\n",
2975 sc->sc_sc1394.sc1394_dev.dv_xname);
2976 #ifdef FW_DEBUG
2977 DPRINTFN(2, ("packet:"));
2978 for (m = m0; m != NULL; m = m->m_next) {
2979 for (n = 0; n < m->m_len; n++)
2980 DPRINTFN(2, ("%s%02x", (n%32)?
2981 ((n%4)?"":" "):"\n ",
2982 mtod(m, u_int8_t *)[n]));
2983 DPRINTFN(2, ("$"));
2984 }
2985 DPRINTFN(2, ("\n"));
2986 #endif
2987 error = EHOSTUNREACH;
2988 goto end;
2989 }
2990 maxrec = 2 << p[8];
2991 spd = p[9];
2992 hdrlen = 0;
2993 }
2994 if (spd > sc->sc_sc1394.sc1394_link_speed) {
2995 DPRINTF(("fwohci_if_output: spd (%d) is faster than %d\n",
2996 spd, sc->sc_sc1394.sc1394_link_speed));
2997 spd = sc->sc_sc1394.sc1394_link_speed;
2998 }
2999 if (maxrec > (512 << spd)) {
3000 DPRINTF(("fwohci_if_output: maxrec (%d) is larger for spd (%d)"
3001 "\n", maxrec, spd));
3002 maxrec = 512 << spd;
3003 }
3004 while (maxrec > sc->sc_sc1394.sc1394_max_receive) {
3005 DPRINTF(("fwohci_if_output: maxrec (%d) is larger than"
3006 " %d\n", maxrec, sc->sc_sc1394.sc1394_max_receive));
3007 maxrec >>= 1;
3008 }
3009 if (maxrec < 512) {
3010 DPRINTF(("fwohci_if_output: maxrec (%d) is smaller than "
3011 "minimum\n", maxrec));
3012 maxrec = 512;
3013 }
3014
3015 m_adj(m0, 16 - hdrlen);
3016 if (m0->m_pkthdr.len > maxrec) {
3017 DPRINTF(("fwohci_if_output: packet too big: hdr %d, pktlen "
3018 "%d, maxrec %d\n", hdrlen, m0->m_pkthdr.len, maxrec));
3019 error = E2BIG; /*XXX*/
3020 goto end;
3021 }
3022
3023 memset(&pkt, 0, sizeof(pkt));
3024 pkt.fp_uio.uio_iov = pkt.fp_iov;
3025 pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
3026 pkt.fp_uio.uio_rw = UIO_WRITE;
3027 if (m0->m_flags & (M_BCAST | M_MCAST)) {
3028 /* construct GASP header */
3029 p = mtod(m0, u_int8_t *);
3030 p[0] = sc->sc_nodeid >> 8;
3031 p[1] = sc->sc_nodeid & 0xff;
3032 p[2] = 0x00; p[3] = 0x00; p[4] = 0x5e;
3033 p[5] = 0x00; p[6] = 0x00; p[7] = 0x01;
3034 pkt.fp_tcode = IEEE1394_TCODE_STREAM_DATA;
3035 pkt.fp_hlen = 8;
3036 pkt.fp_hdr[0] = (spd << 16) | (IEEE1394_TAG_GASP << 14) |
3037 ((sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] &
3038 OHCI_NodeId_NodeNumber) << 8);
3039 pkt.fp_hdr[1] = m0->m_pkthdr.len << 16;
3040 } else {
3041 pkt.fp_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
3042 pkt.fp_hlen = 16;
3043 pkt.fp_hdr[0] = 0x00800100 | (sc->sc_tlabel << 10) |
3044 (spd << 16);
3045 pkt.fp_hdr[1] =
3046 (((sc->sc_nodeid & OHCI_NodeId_BusNumber) | n) << 16) |
3047 (p[10] << 8) | p[11];
3048 pkt.fp_hdr[2] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15];
3049 pkt.fp_hdr[3] = m0->m_pkthdr.len << 16;
3050 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3051 }
3052 pkt.fp_hdr[0] |= (pkt.fp_tcode << 4);
3053 pkt.fp_dlen = m0->m_pkthdr.len;
3054 pkt.fp_m = m0;
3055 pkt.fp_callback = callback;
3056 error = fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
3057 m0 = pkt.fp_m;
3058 end:
3059 if (m0 != NULL) {
3060 if (callback)
3061 (*callback)(sc->sc_sc1394.sc1394_if, m0);
3062 else
3063 m_freem(m0);
3064 }
3065 return error;
3066 }
3067
3068 /*
3069 * High level routines to provide abstraction to attaching layers to
3070 * send/receive data.
3071 */
3072
3073 /*
3074 * These break down into 4 routines as follows:
3075 *
3076 * int fwohci_read(struct ieee1394_abuf *)
3077 *
3078 * This routine will attempt to read a region from the requested node.
3079 * A callback must be provided which will be called when either the completed
3080 * read is done or an unrecoverable error occurs. This is mainly a convenience
3081 * routine since it will encapsulate retrying a region as quadlet vs. block reads
3082 * and recombining all the returned data. This could also be done with a series
3083 * of write/inreg's for each packet sent.
3084 *
3085 * int fwohci_write(struct ieee1394_abuf *)
3086 *
3087 * The work horse main entry point for putting packets on the bus. This is the
3088 * generalized interface for fwnode/etc code to put packets out onto the bus.
3089 * It accepts all standard ieee1394 tcodes (XXX: only a few today) and optionally
3090 * will callback via a func pointer to the calling code with the resulting ACK
3091 * code from the packet. If the ACK code is to be ignored (i.e. no cb) then the
3092 * write routine will take care of free'ing the abuf since the fwnode/etc code
3093 * won't have any knowledge of when to do this. This allows for simple one-off
3094 * packets to be sent from the upper-level code without worrying about a callback
3095 * for cleanup.
3096 *
3097 * int fwohci_inreg(struct ieee1394_abuf *, int)
3098 *
3099 * This is very simple. It evals the abuf passed in and registers an internal
3100 * handler as the callback for packets received for that operation.
3101 * The integer argument specifies whether on a block read/write operation to
3102 * allow sub-regions to be read/written (in block form) as well.
3103 *
3104 * XXX: This whole structure needs to be redone as a list of regions and
3105 * operations allowed on those regions.
3106 *
3107 * int fwohci_unreg(struct ieee1394_abuf *, int)
3108 *
3109 * XXX: TBD. For now passing in a NULL ab_cb to inreg will unregister. This
3110 * routine will simply verify ab_cb is NULL and call inreg.
3111 *
3112 * This simply unregisters the respective callback done via inreg for items
3113 * which only need to register an area for a one-time operation (like a status
3114 * buffer a remote node will write to when the current operation is done). The
3115 * int argument specifies the same behavior as inreg, except in reverse (i.e.
3116 * it unregisters).
3117 */
3118
3119 static int
3120 fwohci_read(struct ieee1394_abuf *ab)
3121 {
3122 struct fwohci_pkt pkt;
3123 struct ieee1394_softc *sc = ab->ab_req;
3124 struct fwohci_softc *psc =
3125 (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3126 struct fwohci_cb *fcb;
3127 u_int32_t high, lo;
3128 int rv, tcode;
3129
3130 /* Have to have a callback when reading. */
3131 if (ab->ab_cb == NULL)
3132 return -1;
3133
3134 fcb = malloc(sizeof(struct fwohci_cb), M_DEVBUF, M_WAITOK);
3135 fcb->ab = ab;
3136 fcb->count = 0;
3137 fcb->abuf_valid = 1;
3138
3139 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3140 lo = (ab->ab_csr & 0x00000000ffffffff);
3141
3142 memset(&pkt, 0, sizeof(pkt));
3143 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3144 pkt.fp_hdr[2] = lo;
3145 pkt.fp_dlen = 0;
3146
3147 if (ab->ab_length == 4) {
3148 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3149 tcode = IEEE1394_TCODE_READ_RESP_QUAD;
3150 pkt.fp_hlen = 12;
3151 } else {
3152 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
3153 pkt.fp_hlen = 16;
3154 tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
3155 pkt.fp_hdr[3] = (ab->ab_length << 16);
3156 }
3157 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3158 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
3159
3160 pkt.fp_statusarg = fcb;
3161 pkt.fp_statuscb = fwohci_read_resp;
3162
3163 rv = fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
3164 psc->sc_tlabel, fwohci_read_resp, fcb);
3165 if (rv)
3166 return rv;
3167 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
3168 if (rv)
3169 fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
3170 psc->sc_tlabel, NULL, NULL);
3171 psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
3172 fcb->count = 1;
3173 return rv;
3174 }
3175
3176 static int
3177 fwohci_write(struct ieee1394_abuf *ab)
3178 {
3179 struct fwohci_pkt pkt;
3180 struct ieee1394_softc *sc = ab->ab_req;
3181 struct fwohci_softc *psc =
3182 (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3183 u_int32_t high, lo;
3184 int rv;
3185
3186 if (ab->ab_length > sc->sc1394_max_receive) {
3187 DPRINTF(("Packet too large: %d\n", ab->ab_length));
3188 return E2BIG;
3189 }
3190
3191 memset(&pkt, 0, sizeof(pkt));
3192
3193 pkt.fp_tcode = ab->ab_tcode;
3194 pkt.fp_uio.uio_iov = pkt.fp_iov;
3195 pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
3196 pkt.fp_uio.uio_rw = UIO_WRITE;
3197
3198 pkt.fp_statusarg = ab;
3199 pkt.fp_statuscb = fwohci_write_ack;
3200
3201 switch (ab->ab_tcode) {
3202 case IEEE1394_TCODE_WRITE_RESP:
3203 pkt.fp_hlen = 12;
3204 case IEEE1394_TCODE_READ_RESP_QUAD:
3205 case IEEE1394_TCODE_READ_RESP_BLOCK:
3206 if (!pkt.fp_hlen)
3207 pkt.fp_hlen = 16;
3208 high = ab->ab_retlen;
3209 ab->ab_retlen = 0;
3210 lo = 0;
3211 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3212 (ab->ab_tlabel << 10) | (pkt.fp_tcode << 4);
3213 break;
3214 default:
3215 pkt.fp_hlen = 16;
3216 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3217 lo = (ab->ab_csr & 0x00000000ffffffff);
3218 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3219 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
3220 break;
3221 }
3222
3223 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3224 pkt.fp_hdr[2] = lo;
3225 if (pkt.fp_hlen == 16) {
3226 if (ab->ab_length == 4) {
3227 pkt.fp_hdr[3] = ab->ab_data[0];
3228 pkt.fp_dlen = 0;
3229 } else {
3230 pkt.fp_hdr[3] = (ab->ab_length << 16);
3231 pkt.fp_dlen = ab->ab_length;
3232 pkt.fp_uio.uio_iovcnt = 1;
3233 pkt.fp_uio.uio_resid = ab->ab_length;
3234 pkt.fp_iov[0].iov_base = ab->ab_data;
3235 pkt.fp_iov[0].iov_len = ab->ab_length;
3236 }
3237 }
3238 switch (ab->ab_tcode) {
3239 case IEEE1394_TCODE_WRITE_RESP:
3240 case IEEE1394_TCODE_READ_RESP_QUAD:
3241 case IEEE1394_TCODE_READ_RESP_BLOCK:
3242 rv = fwohci_at_output(psc, psc->sc_ctx_atrs, &pkt);
3243 break;
3244 default:
3245 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
3246 break;
3247 }
3248 return rv;
3249 }
3250
3251 static int
3252 fwohci_read_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3253 {
3254 struct fwohci_cb *fcb = arg;
3255 struct ieee1394_abuf *ab = fcb->ab;
3256 struct fwohci_pkt newpkt;
3257 u_int32_t *cur, high, lo;
3258 int i, tcode, rcode, status, rv;
3259
3260 /*
3261 * Both the ACK handling and normal response callbacks are handled here.
3262 * The main reason for this is the various error conditions that can
3263 * occur trying to block read some areas and the ways that gets reported
3264 * back to calling station. This is a variety of ACK codes, responses,
3265 * etc which makes it much more difficult to process if both aren't
3266 * handled here.
3267 */
3268
3269 /* Check for status packet. */
3270
3271 if (pkt->fp_tcode == -1) {
3272 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
3273 rcode = -1;
3274 tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
3275 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3276 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
3277 DPRINTF(("Got status packet: 0x%02x\n",
3278 (unsigned int)status));
3279 fcb->count--;
3280
3281 /*
3282 * Got all the ack's back and the buffer is invalid (i.e. the
3283 * callback has been called. Clean up.
3284 */
3285
3286 if (fcb->abuf_valid == 0) {
3287 if (fcb->count == 0)
3288 free(fcb, M_DEVBUF);
3289 return IEEE1394_RCODE_COMPLETE;
3290 }
3291 } else {
3292 status = -1;
3293 tcode = pkt->fp_tcode;
3294 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
3295 }
3296
3297 /*
3298 * Some area's (like the config rom want to be read as quadlets only.
3299 *
3300 * The current ideas to try are:
3301 *
3302 * Got an ACK_TYPE_ERROR on a block read.
3303 *
3304 * Got either RCODE_TYPE or RCODE_ADDRESS errors in a block read
3305 * response.
3306 *
3307 * In all cases construct a new packet for a quadlet read and let
3308 * mutli_resp handle the iteration over the space.
3309 */
3310
3311 if (((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) &&
3312 (tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) ||
3313 (((rcode == IEEE1394_RCODE_TYPE_ERROR) ||
3314 (rcode == IEEE1394_RCODE_ADDRESS_ERROR)) &&
3315 (tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) {
3316
3317 /* Read the area in quadlet chunks (internally track this). */
3318
3319 memset(&newpkt, 0, sizeof(newpkt));
3320
3321 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3322 lo = (ab->ab_csr & 0x00000000ffffffff);
3323
3324 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3325 newpkt.fp_hlen = 12;
3326 newpkt.fp_dlen = 0;
3327 newpkt.fp_hdr[1] =
3328 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3329 newpkt.fp_hdr[2] = lo;
3330 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
3331 (newpkt.fp_tcode << 4);
3332
3333 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3334 ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3335 fwohci_read_multi_resp, fcb);
3336 if (rv) {
3337 (*ab->ab_cb)(ab, -1);
3338 goto cleanup;
3339 }
3340 newpkt.fp_statusarg = fcb;
3341 newpkt.fp_statuscb = fwohci_read_resp;
3342 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
3343 if (rv) {
3344 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3345 ab->ab_req->sc1394_node_id, sc->sc_tlabel, NULL,
3346 NULL);
3347 (*ab->ab_cb)(ab, -1);
3348 goto cleanup;
3349 }
3350 fcb->count++;
3351 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3352 return IEEE1394_RCODE_COMPLETE;
3353 } else if ((rcode != -1) || ((status != -1) &&
3354 (status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3355 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))) {
3356
3357 /*
3358 * Recombine all the iov data into 1 chunk for higher
3359 * level code.
3360 */
3361
3362 if (rcode != -1) {
3363 cur = ab->ab_data;
3364 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
3365 /*
3366 * Make sure and don't exceed the buffer
3367 * allocated for return.
3368 */
3369 if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) >
3370 ab->ab_length) {
3371 memcpy(cur, pkt->fp_iov[i].iov_base,
3372 (ab->ab_length - ab->ab_retlen));
3373 ab->ab_retlen = ab->ab_length;
3374 break;
3375 }
3376 memcpy(cur, pkt->fp_iov[i].iov_base,
3377 pkt->fp_iov[i].iov_len);
3378 cur += pkt->fp_iov[i].iov_len;
3379 ab->ab_retlen += pkt->fp_iov[i].iov_len;
3380 }
3381 }
3382 if (status != -1)
3383 /* XXX: Need a complete tlabel interface. */
3384 for (i = 0; i < 64; i++)
3385 fwohci_handler_set(sc,
3386 IEEE1394_TCODE_READ_RESP_QUAD,
3387 ab->ab_req->sc1394_node_id, i, NULL, NULL);
3388 (*ab->ab_cb)(ab, rcode);
3389 goto cleanup;
3390 } else
3391 /* Good ack packet. */
3392 return IEEE1394_RCODE_COMPLETE;
3393
3394 /* Can't get here unless ab->ab_cb has been called. */
3395
3396 cleanup:
3397 fcb->abuf_valid = 0;
3398 if (fcb->count == 0)
3399 free(fcb, M_DEVBUF);
3400 return IEEE1394_RCODE_COMPLETE;
3401 }
3402
3403 static int
3404 fwohci_read_multi_resp(struct fwohci_softc *sc, void *arg,
3405 struct fwohci_pkt *pkt)
3406 {
3407 struct fwohci_cb *fcb = arg;
3408 struct ieee1394_abuf *ab = fcb->ab;
3409 struct fwohci_pkt newpkt;
3410 u_int32_t high, lo;
3411 int rcode, rv;
3412
3413 /*
3414 * Bad return codes from the wire, just return what's already in the
3415 * buf.
3416 */
3417
3418 /* Make sure a response packet didn't arrive after a bad ACK. */
3419 if (fcb->abuf_valid == 0)
3420 return IEEE1394_RCODE_COMPLETE;
3421
3422 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
3423
3424 if (rcode) {
3425 (*ab->ab_cb)(ab, rcode);
3426 goto cleanup;
3427 }
3428
3429 if ((ab->ab_retlen + pkt->fp_iov[0].iov_len) > ab->ab_length) {
3430 memcpy(((char *)ab->ab_data + ab->ab_retlen),
3431 pkt->fp_iov[0].iov_base, (ab->ab_length - ab->ab_retlen));
3432 ab->ab_retlen = ab->ab_length;
3433 } else {
3434 memcpy(((char *)ab->ab_data + ab->ab_retlen),
3435 pkt->fp_iov[0].iov_base, 4);
3436 ab->ab_retlen += 4;
3437 }
3438 /* Still more, loop and read 4 more bytes. */
3439 if (ab->ab_retlen < ab->ab_length) {
3440 memset(&newpkt, 0, sizeof(newpkt));
3441
3442 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3443 lo = (ab->ab_csr & 0x00000000ffffffff) + ab->ab_retlen;
3444
3445 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3446 newpkt.fp_hlen = 12;
3447 newpkt.fp_dlen = 0;
3448 newpkt.fp_hdr[1] =
3449 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3450 newpkt.fp_hdr[2] = lo;
3451 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
3452 (newpkt.fp_tcode << 4);
3453
3454 newpkt.fp_statusarg = fcb;
3455 newpkt.fp_statuscb = fwohci_read_resp;
3456
3457 /*
3458 * Bad return code. Just give up and return what's
3459 * come in now.
3460 */
3461 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3462 ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3463 fwohci_read_multi_resp, fcb);
3464 if (rv)
3465 (*ab->ab_cb)(ab, -1);
3466 else {
3467 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
3468 if (rv) {
3469 fwohci_handler_set(sc,
3470 IEEE1394_TCODE_READ_RESP_QUAD,
3471 ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3472 NULL, NULL);
3473 (*ab->ab_cb)(ab, -1);
3474 } else {
3475 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3476 fcb->count++;
3477 return IEEE1394_RCODE_COMPLETE;
3478 }
3479 }
3480 } else
3481 (*ab->ab_cb)(ab, IEEE1394_RCODE_COMPLETE);
3482
3483 cleanup:
3484 /* Can't get here unless ab_cb has been called. */
3485 fcb->abuf_valid = 0;
3486 if (fcb->count == 0)
3487 free(fcb, M_DEVBUF);
3488 return IEEE1394_RCODE_COMPLETE;
3489 }
3490
3491 static int
3492 fwohci_write_ack(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3493 {
3494 struct ieee1394_abuf *ab = arg;
3495 u_int16_t status;
3496
3497
3498 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
3499 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3500 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
3501 DPRINTF(("Got status packet: 0x%02x\n",
3502 (unsigned int)status));
3503
3504 /* No callback means this level should free the buffers. */
3505 if (ab->ab_cb)
3506 (*ab->ab_cb)(ab, status);
3507 else {
3508 if (ab->ab_data)
3509 free(ab->ab_data, M_1394DATA);
3510 free(ab, M_1394DATA);
3511 }
3512 return IEEE1394_RCODE_COMPLETE;
3513 }
3514
3515 static int
3516 fwohci_inreg(struct ieee1394_abuf *ab, int allow)
3517 {
3518 struct ieee1394_softc *sc = ab->ab_req;
3519 struct fwohci_softc *psc =
3520 (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3521 u_int32_t high, lo;
3522 int i, j, rv;
3523
3524 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3525 lo = (ab->ab_csr & 0x00000000ffffffff);
3526
3527 rv = 0;
3528 switch (ab->ab_tcode) {
3529 case IEEE1394_TCODE_READ_REQ_QUAD:
3530 case IEEE1394_TCODE_WRITE_REQ_QUAD:
3531 if (ab->ab_cb)
3532 rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo,
3533 fwohci_parse_input, ab);
3534 else
3535 fwohci_handler_set(psc, ab->ab_tcode, high, lo, NULL,
3536 NULL);
3537 break;
3538 case IEEE1394_TCODE_READ_REQ_BLOCK:
3539 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
3540 if (allow) {
3541 for (i = 0; i < (ab->ab_length / 4); i++) {
3542 if (ab->ab_cb) {
3543 rv = fwohci_handler_set(psc,
3544 ab->ab_tcode, high, lo + (i * 4),
3545 fwohci_parse_input, ab);
3546 if (rv)
3547 break;
3548 } else
3549 fwohci_handler_set(psc, ab->ab_tcode,
3550 high, lo + (i * 4), NULL, NULL);
3551 }
3552 if (i != (ab->ab_length / 4)) {
3553 j = i + 1;
3554 for (i = 0; i < j; i++)
3555 fwohci_handler_set(psc, ab->ab_tcode,
3556 high, lo + (i * 4), NULL, NULL);
3557 } else
3558 ab->ab_data = (void *)1;
3559 } else {
3560 if (ab->ab_cb)
3561 rv = fwohci_handler_set(psc, ab->ab_tcode, high,
3562 lo, fwohci_parse_input, ab);
3563 else
3564 fwohci_handler_set(psc, ab->ab_tcode, high, lo,
3565 NULL, NULL);
3566 }
3567 break;
3568 default:
3569 DPRINTF(("Invalid registration tcode: %d\n", ab->ab_tcode));
3570 return -1;
3571 break;
3572 }
3573 return rv;
3574 }
3575
3576 static int
3577 fwohci_parse_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3578 {
3579 struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg;
3580 u_int64_t csr;
3581 u_int32_t *cur;
3582 int i, count;
3583
3584 ab->ab_tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
3585 ab->ab_tlabel = (pkt->fp_hdr[0] >> 10) & 0x3f;
3586 csr = (((u_int64_t)(pkt->fp_hdr[1] & 0xffff) << 32) | pkt->fp_hdr[2]);
3587
3588 switch (ab->ab_tcode) {
3589 case IEEE1394_TCODE_READ_REQ_QUAD:
3590 ab->ab_retlen = 4;
3591 break;
3592 case IEEE1394_TCODE_READ_REQ_BLOCK:
3593 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
3594 if (ab->ab_data) {
3595 if ((csr + ab->ab_retlen) >
3596 (ab->ab_csr + ab->ab_length))
3597 return IEEE1394_RCODE_ADDRESS_ERROR;
3598 ab->ab_data = NULL;
3599 } else
3600 if (ab->ab_retlen != ab->ab_length)
3601 return IEEE1394_RCODE_ADDRESS_ERROR;
3602 break;
3603 case IEEE1394_TCODE_WRITE_REQ_QUAD:
3604 ab->ab_retlen = 4;
3605 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
3606 if (!ab->ab_retlen)
3607 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
3608 if (ab->ab_data) {
3609 if ((csr + ab->ab_retlen) >
3610 (ab->ab_csr + ab->ab_length))
3611 return IEEE1394_RCODE_ADDRESS_ERROR;
3612 ab->ab_data = NULL;
3613 } else
3614 if (ab->ab_retlen != ab->ab_length)
3615 return IEEE1394_RCODE_ADDRESS_ERROR;
3616
3617 ab->ab_data = malloc(ab->ab_retlen, M_1394DATA, M_WAITOK);
3618 if (ab->ab_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD)
3619 ab->ab_data[0] = pkt->fp_hdr[3];
3620 else {
3621 count = 0;
3622 cur = ab->ab_data;
3623 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
3624 memcpy(cur, pkt->fp_iov[i].iov_base,
3625 pkt->fp_iov[i].iov_len);
3626 cur += pkt->fp_iov[i].iov_len;
3627 count += pkt->fp_iov[i].iov_len;
3628 }
3629 if (ab->ab_retlen != count)
3630 panic("Packet claims %d length "
3631 "but only %d bytes returned\n",
3632 ab->ab_retlen, count);
3633 }
3634 break;
3635 default:
3636 panic("Got a callback for a tcode that wasn't requested: %d\n",
3637 ab->ab_tcode);
3638 break;
3639 }
3640 ab->ab_csr = csr;
3641 ab->ab_cb(ab, IEEE1394_RCODE_COMPLETE);
3642 return -1;
3643 }
3644
3645 static int
3646 fwohci_submatch(struct device *parent, struct cfdata *cf, void *aux)
3647 {
3648 struct ieee1394_attach_args *fwa = aux;
3649
3650 /* Both halves must be filled in for a match. */
3651 if ((cf->fwbuscf_idhi == FWBUS_UNK_IDHI &&
3652 cf->fwbuscf_idlo == FWBUS_UNK_IDLO) ||
3653 (cf->fwbuscf_idhi == ntohl(*((u_int32_t *)&fwa->uid[0])) &&
3654 cf->fwbuscf_idlo == ntohl(*((u_int32_t *)&fwa->uid[4]))))
3655 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
3656 return 0;
3657 }
3658
3659 #ifdef FW_DEBUG
3660 static void
3661 fwohci_show_intr(struct fwohci_softc *sc, u_int32_t intmask)
3662 {
3663
3664 printf("%s: intmask=0x%08x:", sc->sc_sc1394.sc1394_dev.dv_xname,
3665 intmask);
3666 if (intmask & OHCI_Int_CycleTooLong)
3667 printf(" CycleTooLong");
3668 if (intmask & OHCI_Int_UnrecoverableError)
3669 printf(" UnrecoverableError");
3670 if (intmask & OHCI_Int_CycleInconsistent)
3671 printf(" CycleInconsistent");
3672 if (intmask & OHCI_Int_BusReset)
3673 printf(" BusReset");
3674 if (intmask & OHCI_Int_SelfIDComplete)
3675 printf(" SelfIDComplete");
3676 if (intmask & OHCI_Int_LockRespErr)
3677 printf(" LockRespErr");
3678 if (intmask & OHCI_Int_PostedWriteErr)
3679 printf(" PostedWriteErr");
3680 if (intmask & OHCI_Int_ReqTxComplete)
3681 printf(" ReqTxComplete(0x%04x)",
3682 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
3683 OHCI_SUBREG_ContextControlClear));
3684 if (intmask & OHCI_Int_RespTxComplete)
3685 printf(" RespTxComplete(0x%04x)",
3686 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
3687 OHCI_SUBREG_ContextControlClear));
3688 if (intmask & OHCI_Int_ARRS)
3689 printf(" ARRS(0x%04x)",
3690 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
3691 OHCI_SUBREG_ContextControlClear));
3692 if (intmask & OHCI_Int_ARRQ)
3693 printf(" ARRQ(0x%04x)",
3694 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
3695 OHCI_SUBREG_ContextControlClear));
3696 if (intmask & OHCI_Int_IsochRx)
3697 printf(" IsochRx(0x%08x)",
3698 OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear));
3699 if (intmask & OHCI_Int_IsochTx)
3700 printf(" IsochTx(0x%08x)",
3701 OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear));
3702 if (intmask & OHCI_Int_RQPkt)
3703 printf(" RQPkt(0x%04x)",
3704 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
3705 OHCI_SUBREG_ContextControlClear));
3706 if (intmask & OHCI_Int_RSPkt)
3707 printf(" RSPkt(0x%04x)",
3708 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
3709 OHCI_SUBREG_ContextControlClear));
3710 printf("\n");
3711 }
3712
3713 static void
3714 fwohci_show_phypkt(struct fwohci_softc *sc, u_int32_t val)
3715 {
3716 u_int8_t key, phyid;
3717
3718 key = (val & 0xc0000000) >> 30;
3719 phyid = (val & 0x3f000000) >> 24;
3720 printf("%s: PHY packet from %d: ",
3721 sc->sc_sc1394.sc1394_dev.dv_xname, phyid);
3722 switch (key) {
3723 case 0:
3724 printf("PHY Config:");
3725 if (val & 0x00800000)
3726 printf(" ForceRoot");
3727 if (val & 0x00400000)
3728 printf(" Gap=%x", (val & 0x003f0000) >> 16);
3729 printf("\n");
3730 break;
3731 case 1:
3732 printf("Link-on\n");
3733 break;
3734 case 2:
3735 printf("SelfID:");
3736 if (val & 0x00800000) {
3737 printf(" #%d", (val & 0x00700000) >> 20);
3738 } else {
3739 if (val & 0x00400000)
3740 printf(" LinkActive");
3741 printf(" Gap=%x", (val & 0x003f0000) >> 16);
3742 printf(" Spd=S%d", 100 << ((val & 0x0000c000) >> 14));
3743 if (val & 0x00000800)
3744 printf(" Cont");
3745 if (val & 0x00000002)
3746 printf(" InitiateBusReset");
3747 }
3748 if (val & 0x00000001)
3749 printf(" +");
3750 printf("\n");
3751 break;
3752 default:
3753 printf("unknown: 0x%08x\n", val);
3754 break;
3755 }
3756 }
3757 #endif /* FW_DEBUG */
3758