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