fwohci.c revision 1.40 1 /* $NetBSD: fwohci.c,v 1.40 2001/07/17 11:01:03 haya Exp $ */
2
3 #define DOUBLEBUF 1
4 #define NO_THREAD 1
5 /*-
6 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Matt Thomas of 3am Software Foundry.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 /*
42 * IEEE1394 Open Host Controller Interface
43 * based on OHCI Specification 1.1 (January 6, 2000)
44 * The first version to support network interface part is wrtten by
45 * Atsushi Onoe <onoe (at) netbsd.org>.
46 */
47
48 /*
49 * The first version to support isochronous acquisition part is wrtten
50 * by HAYAKAWA Koichi <haya (at) netbsd.org>.
51 */
52
53 #include "opt_inet.h"
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/kthread.h>
58 #include <sys/types.h>
59 #include <sys/socket.h>
60 #include <sys/callout.h>
61 #include <sys/device.h>
62 #include <sys/kernel.h>
63 #include <sys/malloc.h>
64 #include <sys/mbuf.h>
65
66 #if __NetBSD_Version__ >= 105010000
67 #include <uvm/uvm_extern.h>
68 #else
69 #include <vm/vm.h>
70 #endif
71
72 #include <machine/bus.h>
73 #include <machine/intr.h>
74
75 #include <dev/ieee1394/ieee1394reg.h>
76 #include <dev/ieee1394/fwohcireg.h>
77
78 #include <dev/ieee1394/ieee1394var.h>
79 #include <dev/ieee1394/fwohcivar.h>
80
81 static const char * const ieee1394_speeds[] = { IEEE1394_SPD_STRINGS };
82
83 #if 0
84 static int fwohci_dnamem_alloc(struct fwohci_softc *sc, int size,
85 int alignment, bus_dmamap_t *mapp, caddr_t *kvap, int flags);
86 #endif
87 static void fwohci_create_event_thread(void *);
88 static void fwohci_thread_init(void *);
89
90 static void fwohci_event_thread(struct fwohci_softc *);
91 static void fwohci_hw_init(struct fwohci_softc *);
92 static void fwohci_power(int, void *);
93 static void fwohci_shutdown(void *);
94
95 static int fwohci_desc_alloc(struct fwohci_softc *);
96 static struct fwohci_desc *fwohci_desc_get(struct fwohci_softc *, int);
97 static void fwohci_desc_put(struct fwohci_softc *, struct fwohci_desc *, int);
98
99 static int fwohci_ctx_alloc(struct fwohci_softc *, struct fwohci_ctx **,
100 int, int, int);
101 static void fwohci_ctx_free(struct fwohci_softc *, struct fwohci_ctx *);
102 static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *);
103
104 static int fwohci_buf_alloc(struct fwohci_softc *, struct fwohci_buf *);
105 static void fwohci_buf_free(struct fwohci_softc *, struct fwohci_buf *);
106 static void fwohci_buf_init_rx(struct fwohci_softc *);
107 static void fwohci_buf_start_rx(struct fwohci_softc *);
108 static void fwohci_buf_stop_tx(struct fwohci_softc *);
109 static void fwohci_buf_stop_rx(struct fwohci_softc *);
110 static void fwohci_buf_next(struct fwohci_softc *, struct fwohci_ctx *);
111 static int fwohci_buf_pktget(struct fwohci_softc *, struct fwohci_buf **,
112 caddr_t *, int);
113 static int fwohci_buf_input(struct fwohci_softc *, struct fwohci_ctx *,
114 struct fwohci_pkt *);
115 static int fwohci_buf_input_ppb(struct fwohci_softc *, struct fwohci_ctx *,
116 struct fwohci_pkt *);
117
118 static u_int8_t fwohci_phy_read(struct fwohci_softc *, u_int8_t);
119 static void fwohci_phy_write(struct fwohci_softc *, u_int8_t, u_int8_t);
120 static void fwohci_phy_busreset(struct fwohci_softc *);
121 static void fwohci_phy_input(struct fwohci_softc *, struct fwohci_pkt *);
122
123 static int fwohci_handler_set(struct fwohci_softc *, int, u_int32_t, u_int32_t,
124 int (*)(struct fwohci_softc *, void *, struct fwohci_pkt *), void *);
125
126 static void fwohci_arrq_input(struct fwohci_softc *, struct fwohci_ctx *);
127 static void fwohci_arrs_input(struct fwohci_softc *, struct fwohci_ctx *);
128 static void fwohci_ir_input(struct fwohci_softc *, struct fwohci_ctx *);
129
130 static int fwohci_at_output(struct fwohci_softc *, struct fwohci_ctx *,
131 struct fwohci_pkt *);
132 static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *, int);
133 static void fwohci_atrs_output(struct fwohci_softc *, int, struct fwohci_pkt *,
134 struct fwohci_pkt *);
135
136 static int fwohci_guidrom_init(struct fwohci_softc *);
137 static void fwohci_configrom_init(struct fwohci_softc *);
138 static int fwohci_configrom_input(struct fwohci_softc *, void *,
139 struct fwohci_pkt *);
140 static void fwohci_selfid_init(struct fwohci_softc *);
141 static int fwohci_selfid_input(struct fwohci_softc *);
142
143 static void fwohci_csr_init(struct fwohci_softc *);
144 static int fwohci_csr_input(struct fwohci_softc *, void *,
145 struct fwohci_pkt *);
146
147 static void fwohci_uid_collect(struct fwohci_softc *);
148 static void fwohci_uid_req(struct fwohci_softc *, int);
149 static int fwohci_uid_input(struct fwohci_softc *, void *,
150 struct fwohci_pkt *);
151 static int fwohci_uid_lookup(struct fwohci_softc *, const u_int8_t *);
152 static void fwohci_check_nodes(struct fwohci_softc *);
153
154 static int fwohci_if_inreg(struct device *, u_int32_t, u_int32_t,
155 void (*)(struct device *, struct mbuf *));
156 static int fwohci_if_input(struct fwohci_softc *, void *, struct fwohci_pkt *);
157 static int fwohci_if_input_iso(struct fwohci_softc *, void *, struct fwohci_pkt *);
158 static int fwohci_if_output(struct device *, struct mbuf *,
159 void (*)(struct device *, struct mbuf *));
160 static int fwohci_if_setiso(struct device *, int, int, int,
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, int channel, int tag, int direction,
283 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
2846 chan = (pkt->fp_hdr[0] & 0x00003f00) >> 8;
2847 tag = (pkt->fp_hdr[0] & 0x0000c000) >> 14;
2848 #ifdef FW_DEBUG
2849 if (fw_verbose) {
2850 int i;
2851 printf("fwohci_if_input_iso: tcode=0x%x, chan=%d, tag=%x, dlen=%d",
2852 pkt->fp_tcode, chan, tag, pkt->fp_dlen);
2853 if (fw_dump) {
2854 for (i = 0; i < pkt->fp_hlen/4; i++)
2855 printf("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i]);
2856 printf("$");
2857 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
2858 iov = &pkt->fp_iov[n];
2859 for (i = 0; i < iov->iov_len; i++)
2860 printf("%s%02x",
2861 (i%32)?((i%4)?"":" "):"\n\t",
2862 ((u_int8_t *)iov->iov_base)[i]);
2863 printf("$");
2864 }
2865 }
2866 printf("\n");
2867 }
2868 #endif /* FW_DEBUG */
2869 len = pkt->fp_dlen;
2870 MGETHDR(m, M_DONTWAIT, MT_DATA);
2871 if (m == NULL)
2872 return IEEE1394_RCODE_COMPLETE;
2873 m->m_len = 16;
2874 if (m->m_len + len > MHLEN) {
2875 MCLGET(m, M_DONTWAIT);
2876 if ((m->m_flags & M_EXT) == 0) {
2877 m_freem(m);
2878 return IEEE1394_RCODE_COMPLETE;
2879 }
2880 }
2881
2882 m->m_flags |= M_BCAST;
2883
2884 if (tag == IEEE1394_TAG_GASP) {
2885 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2886 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
2887 sc->sc_uidtbl[n].fu_valid != 0x3) {
2888 printf("%s: packet from unknown node: phy id %d\n",
2889 sc->sc_sc1394.sc1394_dev.dv_xname, n);
2890 m_freem(m);
2891 return IEEE1394_RCODE_COMPLETE;
2892 }
2893 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
2894 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
2895 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
2896 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */
2897 mtod(m, u_int8_t *)[9] =
2898 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
2899 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
2900 } else {
2901 m->m_flags |= M_LINK0;
2902 }
2903 mtod(m, u_int8_t *)[14] = chan;
2904 mtod(m, u_int8_t *)[15] = tag;
2905
2906
2907 m->m_pkthdr.rcvif = NULL; /* set in child */
2908 m->m_pkthdr.len = len + m->m_len;
2909 /*
2910 * We may use receive buffer by external mbuf instead of copy here.
2911 * But asynchronous receive buffer must be operate in buffer fill
2912 * mode, so that each receive buffer will shared by multiple mbufs.
2913 * If upper layer doesn't free mbuf soon, e.g. application program
2914 * is suspended, buffer must be reallocated.
2915 * Isochronous buffer must be operate in packet buffer mode, and
2916 * it is easy to map receive buffer to external mbuf. But it is
2917 * used for broadcast/multicast only, and is expected not so
2918 * performance sensitive for now.
2919 * XXX: The performance may be important for multicast case,
2920 * so we should revisit here later.
2921 * -- onoe
2922 */
2923 n = 0;
2924 iov = pkt->fp_uio.uio_iov;
2925 while (len > 0) {
2926 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
2927 iov->iov_len);
2928 m->m_len += iov->iov_len;
2929 len -= iov->iov_len;
2930 iov++;
2931 }
2932 (*handler)(sc->sc_sc1394.sc1394_if, m);
2933 return IEEE1394_RCODE_COMPLETE;
2934 }
2935
2936
2937
2938 static int
2939 fwohci_if_output(struct device *self, struct mbuf *m0,
2940 void (*callback)(struct device *, struct mbuf *))
2941 {
2942 struct fwohci_softc *sc = (struct fwohci_softc *)self;
2943 struct fwohci_pkt pkt;
2944 u_int8_t *p;
2945 int n, error, spd, hdrlen, maxrec;
2946 #ifdef FW_DEBUG
2947 struct mbuf *m;
2948 #endif
2949
2950 p = mtod(m0, u_int8_t *);
2951 if (m0->m_flags & (M_BCAST | M_MCAST)) {
2952 spd = IEEE1394_SPD_S100; /*XXX*/
2953 maxrec = 512; /*XXX*/
2954 hdrlen = 8;
2955 } else {
2956 n = fwohci_uid_lookup(sc, p);
2957 if (n < 0) {
2958 printf("%s: nodeid unknown:"
2959 " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
2960 sc->sc_sc1394.sc1394_dev.dv_xname,
2961 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
2962 error = EHOSTUNREACH;
2963 goto end;
2964 }
2965 if (n == IEEE1394_BCAST_PHY_ID) {
2966 printf("%s: broadcast with !M_MCAST\n",
2967 sc->sc_sc1394.sc1394_dev.dv_xname);
2968 #ifdef FW_DEBUG
2969 DPRINTFN(2, ("packet:"));
2970 for (m = m0; m != NULL; m = m->m_next) {
2971 for (n = 0; n < m->m_len; n++)
2972 DPRINTFN(2, ("%s%02x", (n%32)?
2973 ((n%4)?"":" "):"\n ",
2974 mtod(m, u_int8_t *)[n]));
2975 DPRINTFN(2, ("$"));
2976 }
2977 DPRINTFN(2, ("\n"));
2978 #endif
2979 error = EHOSTUNREACH;
2980 goto end;
2981 }
2982 maxrec = 2 << p[8];
2983 spd = p[9];
2984 hdrlen = 0;
2985 }
2986 if (spd > sc->sc_sc1394.sc1394_link_speed) {
2987 DPRINTF(("fwohci_if_output: spd (%d) is faster than %d\n",
2988 spd, sc->sc_sc1394.sc1394_link_speed));
2989 spd = sc->sc_sc1394.sc1394_link_speed;
2990 }
2991 if (maxrec > (512 << spd)) {
2992 DPRINTF(("fwohci_if_output: maxrec (%d) is larger for spd (%d)"
2993 "\n", maxrec, spd));
2994 maxrec = 512 << spd;
2995 }
2996 while (maxrec > sc->sc_sc1394.sc1394_max_receive) {
2997 DPRINTF(("fwohci_if_output: maxrec (%d) is larger than"
2998 " %d\n", maxrec, sc->sc_sc1394.sc1394_max_receive));
2999 maxrec >>= 1;
3000 }
3001 if (maxrec < 512) {
3002 DPRINTF(("fwohci_if_output: maxrec (%d) is smaller than "
3003 "minimum\n", maxrec));
3004 maxrec = 512;
3005 }
3006
3007 m_adj(m0, 16 - hdrlen);
3008 if (m0->m_pkthdr.len > maxrec) {
3009 DPRINTF(("fwohci_if_output: packet too big: hdr %d, pktlen "
3010 "%d, maxrec %d\n", hdrlen, m0->m_pkthdr.len, maxrec));
3011 error = E2BIG; /*XXX*/
3012 goto end;
3013 }
3014
3015 memset(&pkt, 0, sizeof(pkt));
3016 pkt.fp_uio.uio_iov = pkt.fp_iov;
3017 pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
3018 pkt.fp_uio.uio_rw = UIO_WRITE;
3019 if (m0->m_flags & (M_BCAST | M_MCAST)) {
3020 /* construct GASP header */
3021 p = mtod(m0, u_int8_t *);
3022 p[0] = sc->sc_nodeid >> 8;
3023 p[1] = sc->sc_nodeid & 0xff;
3024 p[2] = 0x00; p[3] = 0x00; p[4] = 0x5e;
3025 p[5] = 0x00; p[6] = 0x00; p[7] = 0x01;
3026 pkt.fp_tcode = IEEE1394_TCODE_STREAM_DATA;
3027 pkt.fp_hlen = 8;
3028 pkt.fp_hdr[0] = (spd << 16) | (IEEE1394_TAG_GASP << 14) |
3029 ((sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] &
3030 OHCI_NodeId_NodeNumber) << 8);
3031 pkt.fp_hdr[1] = m0->m_pkthdr.len << 16;
3032 } else {
3033 pkt.fp_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
3034 pkt.fp_hlen = 16;
3035 pkt.fp_hdr[0] = 0x00800100 | (sc->sc_tlabel << 10) |
3036 (spd << 16);
3037 pkt.fp_hdr[1] =
3038 (((sc->sc_nodeid & OHCI_NodeId_BusNumber) | n) << 16) |
3039 (p[10] << 8) | p[11];
3040 pkt.fp_hdr[2] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15];
3041 pkt.fp_hdr[3] = m0->m_pkthdr.len << 16;
3042 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3043 }
3044 pkt.fp_hdr[0] |= (pkt.fp_tcode << 4);
3045 pkt.fp_dlen = m0->m_pkthdr.len;
3046 pkt.fp_m = m0;
3047 pkt.fp_callback = callback;
3048 error = fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
3049 m0 = pkt.fp_m;
3050 end:
3051 if (m0 != NULL) {
3052 if (callback)
3053 (*callback)(sc->sc_sc1394.sc1394_if, m0);
3054 else
3055 m_freem(m0);
3056 }
3057 return error;
3058 }
3059
3060 /*
3061 * High level routines to provide abstraction to attaching layers to
3062 * send/receive data.
3063 */
3064
3065 /*
3066 * These break down into 4 routines as follows:
3067 *
3068 * int fwohci_read(struct ieee1394_abuf *)
3069 *
3070 * This routine will attempt to read a region from the requested node.
3071 * A callback must be provided which will be called when either the completed
3072 * read is done or an unrecoverable error occurs. This is mainly a convenience
3073 * routine since it will encapsulate retrying a region as quadlet vs. block reads
3074 * and recombining all the returned data. This could also be done with a series
3075 * of write/inreg's for each packet sent.
3076 *
3077 * int fwohci_write(struct ieee1394_abuf *)
3078 *
3079 * The work horse main entry point for putting packets on the bus. This is the
3080 * generalized interface for fwnode/etc code to put packets out onto the bus.
3081 * It accepts all standard ieee1394 tcodes (XXX: only a few today) and optionally
3082 * will callback via a func pointer to the calling code with the resulting ACK
3083 * code from the packet. If the ACK code is to be ignored (i.e. no cb) then the
3084 * write routine will take care of free'ing the abuf since the fwnode/etc code
3085 * won't have any knowledge of when to do this. This allows for simple one-off
3086 * packets to be sent from the upper-level code without worrying about a callback
3087 * for cleanup.
3088 *
3089 * int fwohci_inreg(struct ieee1394_abuf *, int)
3090 *
3091 * This is very simple. It evals the abuf passed in and registers an internal
3092 * handler as the callback for packets received for that operation.
3093 * The integer argument specifies whether on a block read/write operation to
3094 * allow sub-regions to be read/written (in block form) as well.
3095 *
3096 * XXX: This whole structure needs to be redone as a list of regions and
3097 * operations allowed on those regions.
3098 *
3099 * int fwohci_unreg(struct ieee1394_abuf *, int)
3100 *
3101 * XXX: TBD. For now passing in a NULL ab_cb to inreg will unregister. This
3102 * routine will simply verify ab_cb is NULL and call inreg.
3103 *
3104 * This simply unregisters the respective callback done via inreg for items
3105 * which only need to register an area for a one-time operation (like a status
3106 * buffer a remote node will write to when the current operation is done). The
3107 * int argument specifies the same behavior as inreg, except in reverse (i.e.
3108 * it unregisters).
3109 */
3110
3111 static int
3112 fwohci_read(struct ieee1394_abuf *ab)
3113 {
3114 struct fwohci_pkt pkt;
3115 struct ieee1394_softc *sc = ab->ab_req;
3116 struct fwohci_softc *psc =
3117 (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3118 struct fwohci_cb *fcb;
3119 u_int32_t high, lo;
3120 int rv, tcode;
3121
3122 /* Have to have a callback when reading. */
3123 if (ab->ab_cb == NULL)
3124 return -1;
3125
3126 fcb = malloc(sizeof(struct fwohci_cb), M_DEVBUF, M_WAITOK);
3127 fcb->ab = ab;
3128 fcb->count = 0;
3129 fcb->abuf_valid = 1;
3130
3131 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3132 lo = (ab->ab_csr & 0x00000000ffffffff);
3133
3134 memset(&pkt, 0, sizeof(pkt));
3135 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3136 pkt.fp_hdr[2] = lo;
3137 pkt.fp_dlen = 0;
3138
3139 if (ab->ab_length == 4) {
3140 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3141 tcode = IEEE1394_TCODE_READ_RESP_QUAD;
3142 pkt.fp_hlen = 12;
3143 } else {
3144 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
3145 pkt.fp_hlen = 16;
3146 tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
3147 pkt.fp_hdr[3] = (ab->ab_length << 16);
3148 }
3149 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3150 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
3151
3152 pkt.fp_statusarg = fcb;
3153 pkt.fp_statuscb = fwohci_read_resp;
3154
3155 rv = fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
3156 psc->sc_tlabel, fwohci_read_resp, fcb);
3157 if (rv)
3158 return rv;
3159 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
3160 if (rv)
3161 fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
3162 psc->sc_tlabel, NULL, NULL);
3163 psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
3164 fcb->count = 1;
3165 return rv;
3166 }
3167
3168 static int
3169 fwohci_write(struct ieee1394_abuf *ab)
3170 {
3171 struct fwohci_pkt pkt;
3172 struct ieee1394_softc *sc = ab->ab_req;
3173 struct fwohci_softc *psc =
3174 (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3175 u_int32_t high, lo;
3176 int rv;
3177
3178 if (ab->ab_length > sc->sc1394_max_receive) {
3179 DPRINTF(("Packet too large: %d\n", ab->ab_length));
3180 return E2BIG;
3181 }
3182
3183 memset(&pkt, 0, sizeof(pkt));
3184
3185 pkt.fp_tcode = ab->ab_tcode;
3186 pkt.fp_uio.uio_iov = pkt.fp_iov;
3187 pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
3188 pkt.fp_uio.uio_rw = UIO_WRITE;
3189
3190 pkt.fp_statusarg = ab;
3191 pkt.fp_statuscb = fwohci_write_ack;
3192
3193 switch (ab->ab_tcode) {
3194 case IEEE1394_TCODE_WRITE_RESP:
3195 pkt.fp_hlen = 12;
3196 case IEEE1394_TCODE_READ_RESP_QUAD:
3197 case IEEE1394_TCODE_READ_RESP_BLOCK:
3198 if (!pkt.fp_hlen)
3199 pkt.fp_hlen = 16;
3200 high = ab->ab_retlen;
3201 ab->ab_retlen = 0;
3202 lo = 0;
3203 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3204 (ab->ab_tlabel << 10) | (pkt.fp_tcode << 4);
3205 break;
3206 default:
3207 pkt.fp_hlen = 16;
3208 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3209 lo = (ab->ab_csr & 0x00000000ffffffff);
3210 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
3211 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
3212 break;
3213 }
3214
3215 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3216 pkt.fp_hdr[2] = lo;
3217 if (pkt.fp_hlen == 16) {
3218 if (ab->ab_length == 4) {
3219 pkt.fp_hdr[3] = ab->ab_data[0];
3220 pkt.fp_dlen = 0;
3221 } else {
3222 pkt.fp_hdr[3] = (ab->ab_length << 16);
3223 pkt.fp_dlen = ab->ab_length;
3224 pkt.fp_uio.uio_iovcnt = 1;
3225 pkt.fp_uio.uio_resid = ab->ab_length;
3226 pkt.fp_iov[0].iov_base = ab->ab_data;
3227 pkt.fp_iov[0].iov_len = ab->ab_length;
3228 }
3229 }
3230 switch (ab->ab_tcode) {
3231 case IEEE1394_TCODE_WRITE_RESP:
3232 case IEEE1394_TCODE_READ_RESP_QUAD:
3233 case IEEE1394_TCODE_READ_RESP_BLOCK:
3234 rv = fwohci_at_output(psc, psc->sc_ctx_atrs, &pkt);
3235 break;
3236 default:
3237 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
3238 break;
3239 }
3240 return rv;
3241 }
3242
3243 static int
3244 fwohci_read_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3245 {
3246 struct fwohci_cb *fcb = arg;
3247 struct ieee1394_abuf *ab = fcb->ab;
3248 struct fwohci_pkt newpkt;
3249 u_int32_t *cur, high, lo;
3250 int i, tcode, rcode, status, rv;
3251
3252 /*
3253 * Both the ACK handling and normal response callbacks are handled here.
3254 * The main reason for this is the various error conditions that can
3255 * occur trying to block read some areas and the ways that gets reported
3256 * back to calling station. This is a variety of ACK codes, responses,
3257 * etc which makes it much more difficult to process if both aren't
3258 * handled here.
3259 */
3260
3261 /* Check for status packet. */
3262
3263 if (pkt->fp_tcode == -1) {
3264 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
3265 rcode = -1;
3266 tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
3267 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3268 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
3269 DPRINTF(("Got status packet: 0x%02x\n",
3270 (unsigned int)status));
3271 fcb->count--;
3272
3273 /*
3274 * Got all the ack's back and the buffer is invalid (i.e. the
3275 * callback has been called. Clean up.
3276 */
3277
3278 if (fcb->abuf_valid == 0) {
3279 if (fcb->count == 0)
3280 free(fcb, M_DEVBUF);
3281 return IEEE1394_RCODE_COMPLETE;
3282 }
3283 } else {
3284 status = -1;
3285 tcode = pkt->fp_tcode;
3286 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
3287 }
3288
3289 /*
3290 * Some area's (like the config rom want to be read as quadlets only.
3291 *
3292 * The current ideas to try are:
3293 *
3294 * Got an ACK_TYPE_ERROR on a block read.
3295 *
3296 * Got either RCODE_TYPE or RCODE_ADDRESS errors in a block read
3297 * response.
3298 *
3299 * In all cases construct a new packet for a quadlet read and let
3300 * mutli_resp handle the iteration over the space.
3301 */
3302
3303 if (((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) &&
3304 (tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) ||
3305 (((rcode == IEEE1394_RCODE_TYPE_ERROR) ||
3306 (rcode == IEEE1394_RCODE_ADDRESS_ERROR)) &&
3307 (tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) {
3308
3309 /* Read the area in quadlet chunks (internally track this). */
3310
3311 memset(&newpkt, 0, sizeof(newpkt));
3312
3313 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3314 lo = (ab->ab_csr & 0x00000000ffffffff);
3315
3316 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3317 newpkt.fp_hlen = 12;
3318 newpkt.fp_dlen = 0;
3319 newpkt.fp_hdr[1] =
3320 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3321 newpkt.fp_hdr[2] = lo;
3322 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
3323 (newpkt.fp_tcode << 4);
3324
3325 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3326 ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3327 fwohci_read_multi_resp, fcb);
3328 if (rv) {
3329 (*ab->ab_cb)(ab, -1);
3330 goto cleanup;
3331 }
3332 newpkt.fp_statusarg = fcb;
3333 newpkt.fp_statuscb = fwohci_read_resp;
3334 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
3335 if (rv) {
3336 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3337 ab->ab_req->sc1394_node_id, sc->sc_tlabel, NULL,
3338 NULL);
3339 (*ab->ab_cb)(ab, -1);
3340 goto cleanup;
3341 }
3342 fcb->count++;
3343 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3344 return IEEE1394_RCODE_COMPLETE;
3345 } else if ((rcode != -1) || ((status != -1) &&
3346 (status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3347 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))) {
3348
3349 /*
3350 * Recombine all the iov data into 1 chunk for higher
3351 * level code.
3352 */
3353
3354 if (rcode != -1) {
3355 cur = ab->ab_data;
3356 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
3357 /*
3358 * Make sure and don't exceed the buffer
3359 * allocated for return.
3360 */
3361 if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) >
3362 ab->ab_length) {
3363 memcpy(cur, pkt->fp_iov[i].iov_base,
3364 (ab->ab_length - ab->ab_retlen));
3365 ab->ab_retlen = ab->ab_length;
3366 break;
3367 }
3368 memcpy(cur, pkt->fp_iov[i].iov_base,
3369 pkt->fp_iov[i].iov_len);
3370 cur += pkt->fp_iov[i].iov_len;
3371 ab->ab_retlen += pkt->fp_iov[i].iov_len;
3372 }
3373 }
3374 if (status != -1)
3375 /* XXX: Need a complete tlabel interface. */
3376 for (i = 0; i < 64; i++)
3377 fwohci_handler_set(sc,
3378 IEEE1394_TCODE_READ_RESP_QUAD,
3379 ab->ab_req->sc1394_node_id, i, NULL, NULL);
3380 (*ab->ab_cb)(ab, rcode);
3381 goto cleanup;
3382 } else
3383 /* Good ack packet. */
3384 return IEEE1394_RCODE_COMPLETE;
3385
3386 /* Can't get here unless ab->ab_cb has been called. */
3387
3388 cleanup:
3389 fcb->abuf_valid = 0;
3390 if (fcb->count == 0)
3391 free(fcb, M_DEVBUF);
3392 return IEEE1394_RCODE_COMPLETE;
3393 }
3394
3395 static int
3396 fwohci_read_multi_resp(struct fwohci_softc *sc, void *arg,
3397 struct fwohci_pkt *pkt)
3398 {
3399 struct fwohci_cb *fcb = arg;
3400 struct ieee1394_abuf *ab = fcb->ab;
3401 struct fwohci_pkt newpkt;
3402 u_int32_t high, lo;
3403 int rcode, rv;
3404
3405 /*
3406 * Bad return codes from the wire, just return what's already in the
3407 * buf.
3408 */
3409
3410 /* Make sure a response packet didn't arrive after a bad ACK. */
3411 if (fcb->abuf_valid == 0)
3412 return IEEE1394_RCODE_COMPLETE;
3413
3414 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
3415
3416 if (rcode) {
3417 (*ab->ab_cb)(ab, rcode);
3418 goto cleanup;
3419 }
3420
3421 if ((ab->ab_retlen + pkt->fp_iov[0].iov_len) > ab->ab_length) {
3422 memcpy(((char *)ab->ab_data + ab->ab_retlen),
3423 pkt->fp_iov[0].iov_base, (ab->ab_length - ab->ab_retlen));
3424 ab->ab_retlen = ab->ab_length;
3425 } else {
3426 memcpy(((char *)ab->ab_data + ab->ab_retlen),
3427 pkt->fp_iov[0].iov_base, 4);
3428 ab->ab_retlen += 4;
3429 }
3430 /* Still more, loop and read 4 more bytes. */
3431 if (ab->ab_retlen < ab->ab_length) {
3432 memset(&newpkt, 0, sizeof(newpkt));
3433
3434 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3435 lo = (ab->ab_csr & 0x00000000ffffffff) + ab->ab_retlen;
3436
3437 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
3438 newpkt.fp_hlen = 12;
3439 newpkt.fp_dlen = 0;
3440 newpkt.fp_hdr[1] =
3441 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high;
3442 newpkt.fp_hdr[2] = lo;
3443 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
3444 (newpkt.fp_tcode << 4);
3445
3446 newpkt.fp_statusarg = fcb;
3447 newpkt.fp_statuscb = fwohci_read_resp;
3448
3449 /*
3450 * Bad return code. Just give up and return what's
3451 * come in now.
3452 */
3453 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
3454 ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3455 fwohci_read_multi_resp, fcb);
3456 if (rv)
3457 (*ab->ab_cb)(ab, -1);
3458 else {
3459 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
3460 if (rv) {
3461 fwohci_handler_set(sc,
3462 IEEE1394_TCODE_READ_RESP_QUAD,
3463 ab->ab_req->sc1394_node_id, sc->sc_tlabel,
3464 NULL, NULL);
3465 (*ab->ab_cb)(ab, -1);
3466 } else {
3467 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
3468 fcb->count++;
3469 return IEEE1394_RCODE_COMPLETE;
3470 }
3471 }
3472 } else
3473 (*ab->ab_cb)(ab, IEEE1394_RCODE_COMPLETE);
3474
3475 cleanup:
3476 /* Can't get here unless ab_cb has been called. */
3477 fcb->abuf_valid = 0;
3478 if (fcb->count == 0)
3479 free(fcb, M_DEVBUF);
3480 return IEEE1394_RCODE_COMPLETE;
3481 }
3482
3483 static int
3484 fwohci_write_ack(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3485 {
3486 struct ieee1394_abuf *ab = arg;
3487 u_int16_t status;
3488
3489
3490 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
3491 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
3492 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))
3493 DPRINTF(("Got status packet: 0x%02x\n",
3494 (unsigned int)status));
3495
3496 /* No callback means this level should free the buffers. */
3497 if (ab->ab_cb)
3498 (*ab->ab_cb)(ab, status);
3499 else {
3500 if (ab->ab_data)
3501 free(ab->ab_data, M_1394DATA);
3502 free(ab, M_1394DATA);
3503 }
3504 return IEEE1394_RCODE_COMPLETE;
3505 }
3506
3507 static int
3508 fwohci_inreg(struct ieee1394_abuf *ab, int allow)
3509 {
3510 struct ieee1394_softc *sc = ab->ab_req;
3511 struct fwohci_softc *psc =
3512 (struct fwohci_softc *)sc->sc1394_dev.dv_parent;
3513 u_int32_t high, lo;
3514 int i, j, rv;
3515
3516 high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
3517 lo = (ab->ab_csr & 0x00000000ffffffff);
3518
3519 rv = 0;
3520 switch (ab->ab_tcode) {
3521 case IEEE1394_TCODE_READ_REQ_QUAD:
3522 case IEEE1394_TCODE_WRITE_REQ_QUAD:
3523 if (ab->ab_cb)
3524 rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo,
3525 fwohci_parse_input, ab);
3526 else
3527 fwohci_handler_set(psc, ab->ab_tcode, high, lo, NULL,
3528 NULL);
3529 break;
3530 case IEEE1394_TCODE_READ_REQ_BLOCK:
3531 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
3532 if (allow) {
3533 for (i = 0; i < (ab->ab_length / 4); i++) {
3534 if (ab->ab_cb) {
3535 rv = fwohci_handler_set(psc,
3536 ab->ab_tcode, high, lo + (i * 4),
3537 fwohci_parse_input, ab);
3538 if (rv)
3539 break;
3540 } else
3541 fwohci_handler_set(psc, ab->ab_tcode,
3542 high, lo + (i * 4), NULL, NULL);
3543 }
3544 if (i != (ab->ab_length / 4)) {
3545 j = i + 1;
3546 for (i = 0; i < j; i++)
3547 fwohci_handler_set(psc, ab->ab_tcode,
3548 high, lo + (i * 4), NULL, NULL);
3549 } else
3550 ab->ab_data = (void *)1;
3551 } else {
3552 if (ab->ab_cb)
3553 rv = fwohci_handler_set(psc, ab->ab_tcode, high,
3554 lo, fwohci_parse_input, ab);
3555 else
3556 fwohci_handler_set(psc, ab->ab_tcode, high, lo,
3557 NULL, NULL);
3558 }
3559 break;
3560 default:
3561 DPRINTF(("Invalid registration tcode: %d\n", ab->ab_tcode));
3562 return -1;
3563 break;
3564 }
3565 return rv;
3566 }
3567
3568 static int
3569 fwohci_parse_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
3570 {
3571 struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg;
3572 u_int64_t csr;
3573 u_int32_t *cur;
3574 int i, count;
3575
3576 ab->ab_tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
3577 ab->ab_tlabel = (pkt->fp_hdr[0] >> 10) & 0x3f;
3578 csr = (((u_int64_t)(pkt->fp_hdr[1] & 0xffff) << 32) | pkt->fp_hdr[2]);
3579
3580 switch (ab->ab_tcode) {
3581 case IEEE1394_TCODE_READ_REQ_QUAD:
3582 ab->ab_retlen = 4;
3583 break;
3584 case IEEE1394_TCODE_READ_REQ_BLOCK:
3585 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
3586 if (ab->ab_data) {
3587 if ((csr + ab->ab_retlen) >
3588 (ab->ab_csr + ab->ab_length))
3589 return IEEE1394_RCODE_ADDRESS_ERROR;
3590 ab->ab_data = NULL;
3591 } else
3592 if (ab->ab_retlen != ab->ab_length)
3593 return IEEE1394_RCODE_ADDRESS_ERROR;
3594 break;
3595 case IEEE1394_TCODE_WRITE_REQ_QUAD:
3596 ab->ab_retlen = 4;
3597 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
3598 if (!ab->ab_retlen)
3599 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff;
3600 if (ab->ab_data) {
3601 if ((csr + ab->ab_retlen) >
3602 (ab->ab_csr + ab->ab_length))
3603 return IEEE1394_RCODE_ADDRESS_ERROR;
3604 ab->ab_data = NULL;
3605 } else
3606 if (ab->ab_retlen != ab->ab_length)
3607 return IEEE1394_RCODE_ADDRESS_ERROR;
3608
3609 ab->ab_data = malloc(ab->ab_retlen, M_1394DATA, M_WAITOK);
3610 if (ab->ab_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD)
3611 ab->ab_data[0] = pkt->fp_hdr[3];
3612 else {
3613 count = 0;
3614 cur = ab->ab_data;
3615 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
3616 memcpy(cur, pkt->fp_iov[i].iov_base,
3617 pkt->fp_iov[i].iov_len);
3618 cur += pkt->fp_iov[i].iov_len;
3619 count += pkt->fp_iov[i].iov_len;
3620 }
3621 if (ab->ab_retlen != count)
3622 panic("Packet claims %d length "
3623 "but only %d bytes returned\n",
3624 ab->ab_retlen, count);
3625 }
3626 break;
3627 default:
3628 panic("Got a callback for a tcode that wasn't requested: %d\n",
3629 ab->ab_tcode);
3630 break;
3631 }
3632 ab->ab_csr = csr;
3633 ab->ab_cb(ab, IEEE1394_RCODE_COMPLETE);
3634 return -1;
3635 }
3636
3637 static int
3638 fwohci_submatch(struct device *parent, struct cfdata *cf, void *aux)
3639 {
3640 struct ieee1394_attach_args *fwa = aux;
3641
3642 /* Both halves must be filled in for a match. */
3643 if ((cf->fwbuscf_idhi == FWBUS_UNK_IDHI &&
3644 cf->fwbuscf_idlo == FWBUS_UNK_IDLO) ||
3645 (cf->fwbuscf_idhi == ntohl(*((u_int32_t *)&fwa->uid[0])) &&
3646 cf->fwbuscf_idlo == ntohl(*((u_int32_t *)&fwa->uid[4]))))
3647 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
3648 return 0;
3649 }
3650
3651 #ifdef FW_DEBUG
3652 static void
3653 fwohci_show_intr(struct fwohci_softc *sc, u_int32_t intmask)
3654 {
3655
3656 printf("%s: intmask=0x%08x:", sc->sc_sc1394.sc1394_dev.dv_xname,
3657 intmask);
3658 if (intmask & OHCI_Int_CycleTooLong)
3659 printf(" CycleTooLong");
3660 if (intmask & OHCI_Int_UnrecoverableError)
3661 printf(" UnrecoverableError");
3662 if (intmask & OHCI_Int_CycleInconsistent)
3663 printf(" CycleInconsistent");
3664 if (intmask & OHCI_Int_BusReset)
3665 printf(" BusReset");
3666 if (intmask & OHCI_Int_SelfIDComplete)
3667 printf(" SelfIDComplete");
3668 if (intmask & OHCI_Int_LockRespErr)
3669 printf(" LockRespErr");
3670 if (intmask & OHCI_Int_PostedWriteErr)
3671 printf(" PostedWriteErr");
3672 if (intmask & OHCI_Int_ReqTxComplete)
3673 printf(" ReqTxComplete(0x%04x)",
3674 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
3675 OHCI_SUBREG_ContextControlClear));
3676 if (intmask & OHCI_Int_RespTxComplete)
3677 printf(" RespTxComplete(0x%04x)",
3678 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
3679 OHCI_SUBREG_ContextControlClear));
3680 if (intmask & OHCI_Int_ARRS)
3681 printf(" ARRS(0x%04x)",
3682 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
3683 OHCI_SUBREG_ContextControlClear));
3684 if (intmask & OHCI_Int_ARRQ)
3685 printf(" ARRQ(0x%04x)",
3686 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
3687 OHCI_SUBREG_ContextControlClear));
3688 if (intmask & OHCI_Int_IsochRx)
3689 printf(" IsochRx(0x%08x)",
3690 OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear));
3691 if (intmask & OHCI_Int_IsochTx)
3692 printf(" IsochTx(0x%08x)",
3693 OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear));
3694 if (intmask & OHCI_Int_RQPkt)
3695 printf(" RQPkt(0x%04x)",
3696 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST,
3697 OHCI_SUBREG_ContextControlClear));
3698 if (intmask & OHCI_Int_RSPkt)
3699 printf(" RSPkt(0x%04x)",
3700 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
3701 OHCI_SUBREG_ContextControlClear));
3702 printf("\n");
3703 }
3704
3705 static void
3706 fwohci_show_phypkt(struct fwohci_softc *sc, u_int32_t val)
3707 {
3708 u_int8_t key, phyid;
3709
3710 key = (val & 0xc0000000) >> 30;
3711 phyid = (val & 0x3f000000) >> 24;
3712 printf("%s: PHY packet from %d: ",
3713 sc->sc_sc1394.sc1394_dev.dv_xname, phyid);
3714 switch (key) {
3715 case 0:
3716 printf("PHY Config:");
3717 if (val & 0x00800000)
3718 printf(" ForceRoot");
3719 if (val & 0x00400000)
3720 printf(" Gap=%x", (val & 0x003f0000) >> 16);
3721 printf("\n");
3722 break;
3723 case 1:
3724 printf("Link-on\n");
3725 break;
3726 case 2:
3727 printf("SelfID:");
3728 if (val & 0x00800000) {
3729 printf(" #%d", (val & 0x00700000) >> 20);
3730 } else {
3731 if (val & 0x00400000)
3732 printf(" LinkActive");
3733 printf(" Gap=%x", (val & 0x003f0000) >> 16);
3734 printf(" Spd=S%d", 100 << ((val & 0x0000c000) >> 14));
3735 if (val & 0x00000800)
3736 printf(" Cont");
3737 if (val & 0x00000002)
3738 printf(" InitiateBusReset");
3739 }
3740 if (val & 0x00000001)
3741 printf(" +");
3742 printf("\n");
3743 break;
3744 default:
3745 printf("unknown: 0x%08x\n", val);
3746 break;
3747 }
3748 }
3749 #endif /* FW_DEBUG */
3750