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