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