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