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