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