1 /* $NetBSD: fwohci.c,v 1.54 2002/03/29 05:06:42 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.54 2002/03/29 05:06:42 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 = 1; 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_PUT_REFER(&cfr, 0x95, 8); /* Unit location */ 2275 CFR_END_UNIT(&cfr); 2276 2277 CFR_START_UNIT(&cfr, 6); 2278 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2279 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */ 2280 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A'); 2281 CFR_END_UNIT(&cfr); 2282 2283 CFR_START_UNIT(&cfr, 7); 2284 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2285 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */ 2286 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '4'); 2287 CFR_END_UNIT(&cfr); 2288 2289 CFR_START_UNIT(&cfr, 8); /* Spec's valid addr range. */ 2290 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2291 CFR_PUT_DATA1(&cfr, (FW_FIFO_LO | 0x1)); 2292 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2293 CFR_PUT_DATA1(&cfr, FW_FIFO_LO); 2294 CFR_END_UNIT(&cfr); 2295 2296 #endif /* INET */ 2297 2298 #ifdef INET6 2299 /* IPv6 unit directory */ 2300 CFR_START_UNIT(&cfr, 4); 2301 CFR_PUT_VALUE(&cfr, 0x12, 0x00005e); /* unit spec id */ 2302 CFR_PUT_REFER(&cfr, 0x81, 9); /* textual descriptor offset */ 2303 CFR_PUT_VALUE(&cfr, 0x13, 0x000002); /* unit sw version */ 2304 /* XXX: TBA by IANA */ 2305 CFR_PUT_REFER(&cfr, 0x81, 10); /* textual descriptor offset */ 2306 CFR_PUT_REFER(&cfr, 0x95, 11); /* Unit location */ 2307 CFR_END_UNIT(&cfr); 2308 2309 CFR_START_UNIT(&cfr, 9); 2310 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2311 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */ 2312 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A'); 2313 CFR_END_UNIT(&cfr); 2314 2315 CFR_START_UNIT(&cfr, 10); 2316 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2317 CFR_PUT_DATA1(&cfr, 0); 2318 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '6'); 2319 CFR_END_UNIT(&cfr); 2320 2321 CFR_START_UNIT(&cfr, 11); /* Spec's valid addr range. */ 2322 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2323 CFR_PUT_DATA1(&cfr, (FW_FIFO_LO | 0x1)); 2324 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2325 CFR_PUT_DATA1(&cfr, FW_FIFO_LO); 2326 CFR_END_UNIT(&cfr); 2327 2328 #endif /* INET6 */ 2329 2330 fb->fb_off = cfr.ptr - hdr; 2331 #ifdef FW_DEBUG 2332 DPRINTF(("%s: Config ROM:", sc->sc_sc1394.sc1394_dev.dv_xname)); 2333 for (i = 0; i < fb->fb_off; i++) 2334 DPRINTF(("%s%08x", i&7?" ":"\n ", hdr[i])); 2335 DPRINTF(("\n")); 2336 #endif /* FW_DEBUG */ 2337 2338 /* 2339 * Make network byte order for DMA 2340 */ 2341 for (i = 0; i < fb->fb_off; i++) 2342 HTONL(hdr[i]); 2343 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, 2344 (caddr_t)cfr.ptr - fb->fb_buf, BUS_DMASYNC_PREWRITE); 2345 2346 OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMmap, 2347 fb->fb_dmamap->dm_segs[0].ds_addr); 2348 2349 /* This register is only valid on OHCI 1.1. */ 2350 val = OHCI_CSR_READ(sc, OHCI_REG_Version); 2351 if ((OHCI_Version_GET_Version(val) == 1) && 2352 (OHCI_Version_GET_Revision(val) == 1)) 2353 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, 2354 OHCI_HCControl_BIBImageValid); 2355 2356 /* Just allow quad reads of the rom. */ 2357 for (i = 0; i < fb->fb_off; i++) 2358 fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD, 2359 CSR_BASE_HI, CSR_BASE_LO + CSR_CONFIG_ROM + (i * 4), 2360 fwohci_configrom_input, NULL); 2361 } 2362 2363 static int 2364 fwohci_configrom_input(struct fwohci_softc *sc, void *arg, 2365 struct fwohci_pkt *pkt) 2366 { 2367 struct fwohci_pkt res; 2368 u_int32_t loc, *rom; 2369 2370 /* This will be used as an array index so size accordingly. */ 2371 loc = pkt->fp_hdr[2] - (CSR_BASE_LO + CSR_CONFIG_ROM); 2372 if ((loc & 0x03) != 0) { 2373 /* alignment error */ 2374 return IEEE1394_RCODE_ADDRESS_ERROR; 2375 } 2376 else 2377 loc /= 4; 2378 rom = (u_int32_t *)sc->sc_buf_cnfrom.fb_buf; 2379 2380 DPRINTFN(1, ("fwohci_configrom_input: ConfigRom[0x%04x]: 0x%08x\n", loc, 2381 ntohl(rom[loc]))); 2382 2383 memset(&res, 0, sizeof(res)); 2384 res.fp_hdr[3] = rom[loc]; 2385 fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res); 2386 return -1; 2387 } 2388 2389 /* 2390 * SelfID buffer (no DMA context) 2391 */ 2392 static void 2393 fwohci_selfid_init(struct fwohci_softc *sc) 2394 { 2395 struct fwohci_buf *fb; 2396 2397 fb = &sc->sc_buf_selfid; 2398 #ifdef DIAGNOSTIC 2399 if ((fb->fb_dmamap->dm_segs[0].ds_addr & 0x7ff) != 0) 2400 panic("fwohci_selfid_init: not aligned: %ld (%ld) %p", 2401 (unsigned long)fb->fb_dmamap->dm_segs[0].ds_addr, 2402 (unsigned long)fb->fb_dmamap->dm_segs[0].ds_len, fb->fb_buf); 2403 #endif 2404 memset(fb->fb_buf, 0, fb->fb_dmamap->dm_segs[0].ds_len); 2405 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, 2406 fb->fb_dmamap->dm_segs[0].ds_len, BUS_DMASYNC_PREREAD); 2407 2408 OHCI_CSR_WRITE(sc, OHCI_REG_SelfIDBuffer, 2409 fb->fb_dmamap->dm_segs[0].ds_addr); 2410 } 2411 2412 static int 2413 fwohci_selfid_input(struct fwohci_softc *sc) 2414 { 2415 int i; 2416 u_int32_t count, val, gen; 2417 u_int32_t *buf; 2418 2419 buf = (u_int32_t *)sc->sc_buf_selfid.fb_buf; 2420 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount); 2421 again: 2422 if (val & OHCI_SelfID_Error) { 2423 printf("%s: SelfID Error\n", sc->sc_sc1394.sc1394_dev.dv_xname); 2424 return -1; 2425 } 2426 count = OHCI_BITVAL(val, OHCI_SelfID_Size); 2427 2428 bus_dmamap_sync(sc->sc_dmat, sc->sc_buf_selfid.fb_dmamap, 2429 0, count << 2, BUS_DMASYNC_POSTREAD); 2430 gen = OHCI_BITVAL(buf[0], OHCI_SelfID_Gen); 2431 2432 #ifdef FW_DEBUG 2433 DPRINTFN(1, ("%s: SelfID: 0x%08x", sc->sc_sc1394.sc1394_dev.dv_xname, 2434 val)); 2435 for (i = 0; i < count; i++) 2436 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ", buf[i])); 2437 DPRINTFN(1, ("\n")); 2438 #endif /* FW_DEBUG */ 2439 2440 for (i = 1; i < count; i += 2) { 2441 if (buf[i] != ~buf[i + 1]) 2442 break; 2443 if (buf[i] & 0x00000001) 2444 continue; /* more pkt */ 2445 if (buf[i] & 0x00800000) 2446 continue; /* external id */ 2447 sc->sc_rootid = (buf[i] & 0x3f000000) >> 24; 2448 if ((buf[i] & 0x00400800) == 0x00400800) 2449 sc->sc_irmid = sc->sc_rootid; 2450 } 2451 2452 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount); 2453 if (OHCI_BITVAL(val, OHCI_SelfID_Gen) != gen) { 2454 if (OHCI_BITVAL(val, OHCI_SelfID_Gen) != 2455 OHCI_BITVAL(buf[0], OHCI_SelfID_Gen)) 2456 goto again; 2457 DPRINTF(("%s: SelfID Gen mismatch (%d, %d)\n", 2458 sc->sc_sc1394.sc1394_dev.dv_xname, gen, 2459 OHCI_BITVAL(val, OHCI_SelfID_Gen))); 2460 return -1; 2461 } 2462 if (i != count) { 2463 printf("%s: SelfID corrupted (%d, 0x%08x, 0x%08x)\n", 2464 sc->sc_sc1394.sc1394_dev.dv_xname, i, buf[i], buf[i + 1]); 2465 #if 1 2466 if (i == 1 && buf[i] == 0 && buf[i + 1] == 0) { 2467 /* 2468 * XXX: CXD3222 sometimes fails to DMA 2469 * selfid packet?? 2470 */ 2471 sc->sc_rootid = (count - 1) / 2 - 1; 2472 sc->sc_irmid = sc->sc_rootid; 2473 } else 2474 #endif 2475 return -1; 2476 } 2477 2478 val = OHCI_CSR_READ(sc, OHCI_REG_NodeId); 2479 if ((val & OHCI_NodeId_IDValid) == 0) { 2480 sc->sc_nodeid = 0xffff; /* invalid */ 2481 printf("%s: nodeid is invalid\n", 2482 sc->sc_sc1394.sc1394_dev.dv_xname); 2483 return -1; 2484 } 2485 sc->sc_nodeid = val & 0xffff; 2486 2487 DPRINTF(("%s: nodeid=0x%04x(%d), rootid=%d, irmid=%d\n", 2488 sc->sc_sc1394.sc1394_dev.dv_xname, sc->sc_nodeid, 2489 sc->sc_nodeid & OHCI_NodeId_NodeNumber, sc->sc_rootid, 2490 sc->sc_irmid)); 2491 2492 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid) 2493 return -1; 2494 2495 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == sc->sc_rootid) 2496 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet, 2497 OHCI_LinkControl_CycleMaster); 2498 else 2499 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear, 2500 OHCI_LinkControl_CycleMaster); 2501 return 0; 2502 } 2503 2504 /* 2505 * some CSRs are handled by driver. 2506 */ 2507 static void 2508 fwohci_csr_init(struct fwohci_softc *sc) 2509 { 2510 int i; 2511 static u_int32_t csr[] = { 2512 CSR_STATE_CLEAR, CSR_STATE_SET, CSR_SB_CYCLE_TIME, 2513 CSR_SB_BUS_TIME, CSR_SB_BUSY_TIMEOUT, CSR_SB_BUS_MANAGER_ID, 2514 CSR_SB_CHANNEL_AVAILABLE_HI, CSR_SB_CHANNEL_AVAILABLE_LO, 2515 CSR_SB_BROADCAST_CHANNEL 2516 }; 2517 2518 for (i = 0; i < sizeof(csr) / sizeof(csr[0]); i++) { 2519 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_QUAD, 2520 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL); 2521 fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD, 2522 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL); 2523 } 2524 sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] = 31; /*XXX*/ 2525 } 2526 2527 static int 2528 fwohci_csr_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 2529 { 2530 struct fwohci_pkt res; 2531 u_int32_t reg; 2532 2533 /* 2534 * XXX need to do special functionality other than just r/w... 2535 */ 2536 reg = pkt->fp_hdr[2] - CSR_BASE_LO; 2537 2538 if ((reg & 0x03) != 0) { 2539 /* alignment error */ 2540 return IEEE1394_RCODE_ADDRESS_ERROR; 2541 } 2542 DPRINTFN(1, ("fwohci_csr_input: CSR[0x%04x]: 0x%08x", reg, 2543 *(u_int32_t *)(&sc->sc_csr[reg]))); 2544 if (pkt->fp_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) { 2545 DPRINTFN(1, (" -> 0x%08x\n", 2546 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base))); 2547 *(u_int32_t *)&sc->sc_csr[reg] = 2548 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base); 2549 } else { 2550 DPRINTFN(1, ("\n")); 2551 res.fp_hdr[3] = htonl(*(u_int32_t *)&sc->sc_csr[reg]); 2552 res.fp_iov[0].iov_base = &res.fp_hdr[3]; 2553 res.fp_iov[0].iov_len = 4; 2554 res.fp_uio.uio_resid = 4; 2555 res.fp_uio.uio_iovcnt = 1; 2556 fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res); 2557 return -1; 2558 } 2559 return IEEE1394_RCODE_COMPLETE; 2560 } 2561 2562 /* 2563 * Mapping between nodeid and unique ID (EUI-64). 2564 * 2565 * Track old mappings and simply update their devices with the new id's when 2566 * they match an existing EUI. This allows proper renumeration of the bus. 2567 */ 2568 static void 2569 fwohci_uid_collect(struct fwohci_softc *sc) 2570 { 2571 int i; 2572 struct fwohci_uidtbl *fu; 2573 struct ieee1394_softc *iea; 2574 2575 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) 2576 iea->sc1394_node_id = 0xffff; 2577 2578 if (sc->sc_uidtbl != NULL) 2579 free(sc->sc_uidtbl, M_DEVBUF); 2580 sc->sc_uidtbl = malloc(sizeof(*fu) * (sc->sc_rootid + 1), M_DEVBUF, 2581 M_NOWAIT|M_ZERO); /* XXX M_WAITOK requires locks */ 2582 if (sc->sc_uidtbl == NULL) 2583 return; 2584 2585 for (i = 0, fu = sc->sc_uidtbl; i <= sc->sc_rootid; i++, fu++) { 2586 if (i == (sc->sc_nodeid & OHCI_NodeId_NodeNumber)) { 2587 memcpy(fu->fu_uid, sc->sc_sc1394.sc1394_guid, 8); 2588 fu->fu_valid = 3; 2589 2590 iea = (struct ieee1394_softc *)sc->sc_sc1394.sc1394_if; 2591 if (iea) { 2592 iea->sc1394_node_id = i; 2593 DPRINTF(("%s: Updating nodeid to %d\n", 2594 iea->sc1394_dev.dv_xname, 2595 iea->sc1394_node_id)); 2596 } 2597 } else { 2598 fu->fu_valid = 0; 2599 fwohci_uid_req(sc, i); 2600 } 2601 } 2602 if (sc->sc_rootid == 0) 2603 fwohci_check_nodes(sc); 2604 } 2605 2606 static void 2607 fwohci_uid_req(struct fwohci_softc *sc, int phyid) 2608 { 2609 struct fwohci_pkt pkt; 2610 2611 memset(&pkt, 0, sizeof(pkt)); 2612 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 2613 pkt.fp_hlen = 12; 2614 pkt.fp_dlen = 0; 2615 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 2616 (pkt.fp_tcode << 4); 2617 pkt.fp_hdr[1] = ((0xffc0 | phyid) << 16) | CSR_BASE_HI; 2618 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12; 2619 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid, 2620 sc->sc_tlabel, fwohci_uid_input, (void *)0); 2621 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 2622 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt); 2623 2624 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 2625 (pkt.fp_tcode << 4); 2626 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16; 2627 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid, 2628 sc->sc_tlabel, fwohci_uid_input, (void *)1); 2629 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 2630 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt); 2631 } 2632 2633 static int 2634 fwohci_uid_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *res) 2635 { 2636 struct fwohci_uidtbl *fu; 2637 struct ieee1394_softc *iea; 2638 struct ieee1394_attach_args fwa; 2639 int i, n, done, rcode, found; 2640 2641 found = 0; 2642 2643 n = (res->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber; 2644 rcode = (res->fp_hdr[1] & 0x0000f000) >> 12; 2645 if (rcode != IEEE1394_RCODE_COMPLETE || 2646 sc->sc_uidtbl == NULL || 2647 n > sc->sc_rootid) 2648 return 0; 2649 fu = &sc->sc_uidtbl[n]; 2650 if (arg == 0) { 2651 memcpy(fu->fu_uid, res->fp_iov[0].iov_base, 4); 2652 fu->fu_valid |= 0x1; 2653 } else { 2654 memcpy(fu->fu_uid + 4, res->fp_iov[0].iov_base, 4); 2655 fu->fu_valid |= 0x2; 2656 } 2657 #ifdef FW_DEBUG 2658 if (fu->fu_valid == 0x3) 2659 DPRINTFN(1, ("fwohci_uid_input: " 2660 "Node %d, UID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", n, 2661 fu->fu_uid[0], fu->fu_uid[1], fu->fu_uid[2], fu->fu_uid[3], 2662 fu->fu_uid[4], fu->fu_uid[5], fu->fu_uid[6], fu->fu_uid[7])); 2663 #endif 2664 if (fu->fu_valid == 0x3) { 2665 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) 2666 if (memcmp(iea->sc1394_guid, fu->fu_uid, 8) == 0) { 2667 found = 1; 2668 iea->sc1394_node_id = n; 2669 DPRINTF(("%s: Updating nodeid to %d\n", 2670 iea->sc1394_dev.dv_xname, 2671 iea->sc1394_node_id)); 2672 break; 2673 } 2674 if (!found) { 2675 strcpy(fwa.name, "fwnode"); 2676 memcpy(fwa.uid, fu->fu_uid, 8); 2677 fwa.nodeid = n; 2678 fwa.read = fwohci_read; 2679 fwa.write = fwohci_write; 2680 fwa.inreg = fwohci_inreg; 2681 fwa.unreg = fwohci_unreg; 2682 iea = (struct ieee1394_softc *) 2683 config_found_sm(&sc->sc_sc1394.sc1394_dev, &fwa, 2684 fwohci_print, fwohci_submatch); 2685 if (iea != NULL) 2686 LIST_INSERT_HEAD(&sc->sc_nodelist, iea, 2687 sc1394_node); 2688 } 2689 } 2690 done = 1; 2691 2692 for (i = 0; i < sc->sc_rootid + 1; i++) { 2693 fu = &sc->sc_uidtbl[i]; 2694 if (fu->fu_valid != 0x3) { 2695 done = 0; 2696 break; 2697 } 2698 } 2699 if (done) 2700 fwohci_check_nodes(sc); 2701 2702 return 0; 2703 } 2704 2705 static void 2706 fwohci_check_nodes(struct fwohci_softc *sc) 2707 { 2708 struct device *detach = NULL; 2709 struct ieee1394_softc *iea; 2710 2711 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) { 2712 2713 /* 2714 * Have to defer detachment until the next 2715 * loop iteration since config_detach 2716 * free's the softc and the loop iterator 2717 * needs data from the softc to move 2718 * forward. 2719 */ 2720 2721 if (detach) { 2722 config_detach(detach, 0); 2723 detach = NULL; 2724 } 2725 if (iea->sc1394_node_id == 0xffff) { 2726 detach = (struct device *)iea; 2727 LIST_REMOVE(iea, sc1394_node); 2728 } 2729 } 2730 if (detach) 2731 config_detach(detach, 0); 2732 } 2733 2734 static int 2735 fwohci_uid_lookup(struct fwohci_softc *sc, const u_int8_t *uid) 2736 { 2737 struct fwohci_uidtbl *fu; 2738 int n; 2739 static const u_int8_t bcast[] = 2740 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 2741 2742 fu = sc->sc_uidtbl; 2743 if (fu == NULL) { 2744 if (memcmp(uid, bcast, sizeof(bcast)) == 0) 2745 return IEEE1394_BCAST_PHY_ID; 2746 fwohci_uid_collect(sc); /* try to get */ 2747 return -1; 2748 } 2749 for (n = 0; n <= sc->sc_rootid; n++, fu++) { 2750 if (fu->fu_valid == 0x3 && memcmp(fu->fu_uid, uid, 8) == 0) 2751 return n; 2752 } 2753 if (memcmp(uid, bcast, sizeof(bcast)) == 0) 2754 return IEEE1394_BCAST_PHY_ID; 2755 for (n = 0, fu = sc->sc_uidtbl; n <= sc->sc_rootid; n++, fu++) { 2756 if (fu->fu_valid != 0x3) { 2757 /* 2758 * XXX: need timer before retransmission 2759 */ 2760 fwohci_uid_req(sc, n); 2761 } 2762 } 2763 return -1; 2764 } 2765 2766 /* 2767 * functions to support network interface 2768 */ 2769 static int 2770 fwohci_if_inreg(struct device *self, u_int32_t offhi, u_int32_t offlo, 2771 void (*handler)(struct device *, struct mbuf *)) 2772 { 2773 struct fwohci_softc *sc = (struct fwohci_softc *)self; 2774 2775 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_BLOCK, offhi, offlo, 2776 handler ? fwohci_if_input : NULL, handler); 2777 fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA, 2778 (sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & IEEE1394_ISOCH_MASK) | 2779 OHCI_ASYNC_STREAM, 2780 IEEE1394_TAG_GASP, handler ? fwohci_if_input : NULL, handler); 2781 return 0; 2782 } 2783 2784 static int 2785 fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 2786 { 2787 int n, len; 2788 struct mbuf *m; 2789 struct iovec *iov; 2790 void (*handler)(struct device *, struct mbuf *) = arg; 2791 2792 #ifdef FW_DEBUG 2793 int i; 2794 DPRINTFN(1, ("fwohci_if_input: tcode=0x%x, dlen=%d", pkt->fp_tcode, 2795 pkt->fp_dlen)); 2796 for (i = 0; i < pkt->fp_hlen/4; i++) 2797 DPRINTFN(2, ("%s%08x", i?" ":"\n ", pkt->fp_hdr[i])); 2798 DPRINTFN(2, ("$")); 2799 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){ 2800 iov = &pkt->fp_iov[n]; 2801 for (i = 0; i < iov->iov_len; i++) 2802 DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n ", 2803 ((u_int8_t *)iov->iov_base)[i])); 2804 DPRINTFN(2, ("$")); 2805 } 2806 DPRINTFN(1, ("\n")); 2807 #endif /* FW_DEBUG */ 2808 len = pkt->fp_dlen; 2809 MGETHDR(m, M_DONTWAIT, MT_DATA); 2810 if (m == NULL) 2811 return IEEE1394_RCODE_COMPLETE; 2812 m->m_len = 16; 2813 if (len + m->m_len > MHLEN) { 2814 MCLGET(m, M_DONTWAIT); 2815 if ((m->m_flags & M_EXT) == 0) { 2816 m_freem(m); 2817 return IEEE1394_RCODE_COMPLETE; 2818 } 2819 } 2820 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber; 2821 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid || 2822 sc->sc_uidtbl[n].fu_valid != 0x3) { 2823 printf("%s: packet from unknown node: phy id %d\n", 2824 sc->sc_sc1394.sc1394_dev.dv_xname, n); 2825 m_freem(m); 2826 fwohci_uid_req(sc, n); 2827 return IEEE1394_RCODE_COMPLETE; 2828 } 2829 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8); 2830 if (pkt->fp_tcode == IEEE1394_TCODE_STREAM_DATA) { 2831 m->m_flags |= M_BCAST; 2832 mtod(m, u_int32_t *)[2] = mtod(m, u_int32_t *)[3] = 0; 2833 } else { 2834 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]); 2835 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]); 2836 } 2837 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */ 2838 mtod(m, u_int8_t *)[9] = 2839 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) & 2840 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1); 2841 2842 m->m_pkthdr.rcvif = NULL; /* set in child */ 2843 m->m_pkthdr.len = len + m->m_len; 2844 /* 2845 * We may use receive buffer by external mbuf instead of copy here. 2846 * But asynchronous receive buffer must be operate in buffer fill 2847 * mode, so that each receive buffer will shared by multiple mbufs. 2848 * If upper layer doesn't free mbuf soon, e.g. application program 2849 * is suspended, buffer must be reallocated. 2850 * Isochronous buffer must be operate in packet buffer mode, and 2851 * it is easy to map receive buffer to external mbuf. But it is 2852 * used for broadcast/multicast only, and is expected not so 2853 * performance sensitive for now. 2854 * XXX: The performance may be important for multicast case, 2855 * so we should revisit here later. 2856 * -- onoe 2857 */ 2858 n = 0; 2859 iov = pkt->fp_uio.uio_iov; 2860 while (len > 0) { 2861 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base, 2862 iov->iov_len); 2863 m->m_len += iov->iov_len; 2864 len -= iov->iov_len; 2865 iov++; 2866 } 2867 (*handler)(sc->sc_sc1394.sc1394_if, m); 2868 return IEEE1394_RCODE_COMPLETE; 2869 } 2870 2871 static int 2872 fwohci_if_input_iso(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 2873 { 2874 int n, len; 2875 int chan, tag; 2876 struct mbuf *m; 2877 struct iovec *iov; 2878 void (*handler)(struct device *, struct mbuf *) = arg; 2879 #ifdef FW_DEBUG 2880 int i; 2881 #endif 2882 2883 chan = (pkt->fp_hdr[0] & 0x00003f00) >> 8; 2884 tag = (pkt->fp_hdr[0] & 0x0000c000) >> 14; 2885 #ifdef FW_DEBUG 2886 DPRINTFN(1, ("fwohci_if_input_iso: " 2887 "tcode=0x%x, chan=%d, tag=%x, dlen=%d", 2888 pkt->fp_tcode, chan, tag, pkt->fp_dlen)); 2889 for (i = 0; i < pkt->fp_hlen/4; i++) 2890 DPRINTFN(2, ("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i])); 2891 DPRINTFN(2, ("$")); 2892 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){ 2893 iov = &pkt->fp_iov[n]; 2894 for (i = 0; i < iov->iov_len; i++) 2895 DPRINTFN(2, ("%s%02x", 2896 (i%32)?((i%4)?"":" "):"\n\t", 2897 ((u_int8_t *)iov->iov_base)[i])); 2898 DPRINTFN(2, ("$")); 2899 } 2900 DPRINTFN(2, ("\n")); 2901 #endif /* FW_DEBUG */ 2902 len = pkt->fp_dlen; 2903 MGETHDR(m, M_DONTWAIT, MT_DATA); 2904 if (m == NULL) 2905 return IEEE1394_RCODE_COMPLETE; 2906 m->m_len = 16; 2907 if (m->m_len + len > MHLEN) { 2908 MCLGET(m, M_DONTWAIT); 2909 if ((m->m_flags & M_EXT) == 0) { 2910 m_freem(m); 2911 return IEEE1394_RCODE_COMPLETE; 2912 } 2913 } 2914 2915 m->m_flags |= M_BCAST; 2916 2917 if (tag == IEEE1394_TAG_GASP) { 2918 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber; 2919 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid || 2920 sc->sc_uidtbl[n].fu_valid != 0x3) { 2921 printf("%s: packet from unknown node: phy id %d\n", 2922 sc->sc_sc1394.sc1394_dev.dv_xname, n); 2923 m_freem(m); 2924 return IEEE1394_RCODE_COMPLETE; 2925 } 2926 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8); 2927 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]); 2928 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]); 2929 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */ 2930 mtod(m, u_int8_t *)[9] = 2931 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) & 2932 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1); 2933 } else { 2934 m->m_flags |= M_LINK0; 2935 } 2936 mtod(m, u_int8_t *)[14] = chan; 2937 mtod(m, u_int8_t *)[15] = tag; 2938 2939 2940 m->m_pkthdr.rcvif = NULL; /* set in child */ 2941 m->m_pkthdr.len = len + m->m_len; 2942 /* 2943 * We may use receive buffer by external mbuf instead of copy here. 2944 * But asynchronous receive buffer must be operate in buffer fill 2945 * mode, so that each receive buffer will shared by multiple mbufs. 2946 * If upper layer doesn't free mbuf soon, e.g. application program 2947 * is suspended, buffer must be reallocated. 2948 * Isochronous buffer must be operate in packet buffer mode, and 2949 * it is easy to map receive buffer to external mbuf. But it is 2950 * used for broadcast/multicast only, and is expected not so 2951 * performance sensitive for now. 2952 * XXX: The performance may be important for multicast case, 2953 * so we should revisit here later. 2954 * -- onoe 2955 */ 2956 n = 0; 2957 iov = pkt->fp_uio.uio_iov; 2958 while (len > 0) { 2959 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base, 2960 iov->iov_len); 2961 m->m_len += iov->iov_len; 2962 len -= iov->iov_len; 2963 iov++; 2964 } 2965 (*handler)(sc->sc_sc1394.sc1394_if, m); 2966 return IEEE1394_RCODE_COMPLETE; 2967 } 2968 2969 2970 2971 static int 2972 fwohci_if_output(struct device *self, struct mbuf *m0, 2973 void (*callback)(struct device *, struct mbuf *)) 2974 { 2975 struct fwohci_softc *sc = (struct fwohci_softc *)self; 2976 struct fwohci_pkt pkt; 2977 u_int8_t *p; 2978 int n, error, spd, hdrlen, maxrec; 2979 #ifdef FW_DEBUG 2980 struct mbuf *m; 2981 #endif 2982 2983 p = mtod(m0, u_int8_t *); 2984 if (m0->m_flags & (M_BCAST | M_MCAST)) { 2985 spd = IEEE1394_SPD_S100; /*XXX*/ 2986 maxrec = 512; /*XXX*/ 2987 hdrlen = 8; 2988 } else { 2989 n = fwohci_uid_lookup(sc, p); 2990 if (n < 0) { 2991 printf("%s: nodeid unknown:" 2992 " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 2993 sc->sc_sc1394.sc1394_dev.dv_xname, 2994 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 2995 error = EHOSTUNREACH; 2996 goto end; 2997 } 2998 if (n == IEEE1394_BCAST_PHY_ID) { 2999 printf("%s: broadcast with !M_MCAST\n", 3000 sc->sc_sc1394.sc1394_dev.dv_xname); 3001 #ifdef FW_DEBUG 3002 DPRINTFN(2, ("packet:")); 3003 for (m = m0; m != NULL; m = m->m_next) { 3004 for (n = 0; n < m->m_len; n++) 3005 DPRINTFN(2, ("%s%02x", (n%32)? 3006 ((n%4)?"":" "):"\n ", 3007 mtod(m, u_int8_t *)[n])); 3008 DPRINTFN(2, ("$")); 3009 } 3010 DPRINTFN(2, ("\n")); 3011 #endif 3012 error = EHOSTUNREACH; 3013 goto end; 3014 } 3015 maxrec = 2 << p[8]; 3016 spd = p[9]; 3017 hdrlen = 0; 3018 } 3019 if (spd > sc->sc_sc1394.sc1394_link_speed) { 3020 DPRINTF(("fwohci_if_output: spd (%d) is faster than %d\n", 3021 spd, sc->sc_sc1394.sc1394_link_speed)); 3022 spd = sc->sc_sc1394.sc1394_link_speed; 3023 } 3024 if (maxrec > (512 << spd)) { 3025 DPRINTF(("fwohci_if_output: maxrec (%d) is larger for spd (%d)" 3026 "\n", maxrec, spd)); 3027 maxrec = 512 << spd; 3028 } 3029 while (maxrec > sc->sc_sc1394.sc1394_max_receive) { 3030 DPRINTF(("fwohci_if_output: maxrec (%d) is larger than" 3031 " %d\n", maxrec, sc->sc_sc1394.sc1394_max_receive)); 3032 maxrec >>= 1; 3033 } 3034 if (maxrec < 512) { 3035 DPRINTF(("fwohci_if_output: maxrec (%d) is smaller than " 3036 "minimum\n", maxrec)); 3037 maxrec = 512; 3038 } 3039 3040 m_adj(m0, 16 - hdrlen); 3041 if (m0->m_pkthdr.len > maxrec) { 3042 DPRINTF(("fwohci_if_output: packet too big: hdr %d, pktlen " 3043 "%d, maxrec %d\n", hdrlen, m0->m_pkthdr.len, maxrec)); 3044 error = E2BIG; /*XXX*/ 3045 goto end; 3046 } 3047 3048 memset(&pkt, 0, sizeof(pkt)); 3049 pkt.fp_uio.uio_iov = pkt.fp_iov; 3050 pkt.fp_uio.uio_segflg = UIO_SYSSPACE; 3051 pkt.fp_uio.uio_rw = UIO_WRITE; 3052 if (m0->m_flags & (M_BCAST | M_MCAST)) { 3053 /* construct GASP header */ 3054 p = mtod(m0, u_int8_t *); 3055 p[0] = sc->sc_nodeid >> 8; 3056 p[1] = sc->sc_nodeid & 0xff; 3057 p[2] = 0x00; p[3] = 0x00; p[4] = 0x5e; 3058 p[5] = 0x00; p[6] = 0x00; p[7] = 0x01; 3059 pkt.fp_tcode = IEEE1394_TCODE_STREAM_DATA; 3060 pkt.fp_hlen = 8; 3061 pkt.fp_hdr[0] = (spd << 16) | (IEEE1394_TAG_GASP << 14) | 3062 ((sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & 3063 OHCI_NodeId_NodeNumber) << 8); 3064 pkt.fp_hdr[1] = m0->m_pkthdr.len << 16; 3065 } else { 3066 pkt.fp_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; 3067 pkt.fp_hlen = 16; 3068 pkt.fp_hdr[0] = 0x00800100 | (sc->sc_tlabel << 10) | 3069 (spd << 16); 3070 pkt.fp_hdr[1] = 3071 (((sc->sc_nodeid & OHCI_NodeId_BusNumber) | n) << 16) | 3072 (p[10] << 8) | p[11]; 3073 pkt.fp_hdr[2] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; 3074 pkt.fp_hdr[3] = m0->m_pkthdr.len << 16; 3075 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 3076 } 3077 pkt.fp_hdr[0] |= (pkt.fp_tcode << 4); 3078 pkt.fp_dlen = m0->m_pkthdr.len; 3079 pkt.fp_m = m0; 3080 pkt.fp_callback = callback; 3081 error = fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt); 3082 m0 = pkt.fp_m; 3083 end: 3084 if (m0 != NULL) { 3085 if (callback) 3086 (*callback)(sc->sc_sc1394.sc1394_if, m0); 3087 else 3088 m_freem(m0); 3089 } 3090 return error; 3091 } 3092 3093 /* 3094 * High level routines to provide abstraction to attaching layers to 3095 * send/receive data. 3096 */ 3097 3098 /* 3099 * These break down into 4 routines as follows: 3100 * 3101 * int fwohci_read(struct ieee1394_abuf *) 3102 * 3103 * This routine will attempt to read a region from the requested node. 3104 * A callback must be provided which will be called when either the completed 3105 * read is done or an unrecoverable error occurs. This is mainly a convenience 3106 * routine since it will encapsulate retrying a region as quadlet vs. block 3107 * reads and recombining all the returned data. This could also be done with a 3108 * series of write/inreg's for each packet sent. 3109 * 3110 * int fwohci_write(struct ieee1394_abuf *) 3111 * 3112 * The work horse main entry point for putting packets on the bus. This is the 3113 * generalized interface for fwnode/etc code to put packets out onto the bus. 3114 * It accepts all standard ieee1394 tcodes (XXX: only a few today) and 3115 * optionally will callback via a func pointer to the calling code with the 3116 * resulting ACK code from the packet. If the ACK code is to be ignored (i.e. 3117 * no cb) then the write routine will take care of free'ing the abuf since the 3118 * fwnode/etc code won't have any knowledge of when to do this. This allows for 3119 * simple one-off packets to be sent from the upper-level code without worrying 3120 * about a callback for cleanup. 3121 * 3122 * int fwohci_inreg(struct ieee1394_abuf *, int) 3123 * 3124 * This is very simple. It evals the abuf passed in and registers an internal 3125 * handler as the callback for packets received for that operation. 3126 * The integer argument specifies whether on a block read/write operation to 3127 * allow sub-regions to be read/written (in block form) as well. 3128 * 3129 * XXX: This whole structure needs to be redone as a list of regions and 3130 * operations allowed on those regions. 3131 * 3132 * int fwohci_unreg(struct ieee1394_abuf *, int) 3133 * 3134 * This simply unregisters the respective callback done via inreg for items 3135 * which only need to register an area for a one-time operation (like a status 3136 * buffer a remote node will write to when the current operation is done). The 3137 * int argument specifies the same behavior as inreg, except in reverse (i.e. 3138 * it unregisters). 3139 */ 3140 3141 static int 3142 fwohci_read(struct ieee1394_abuf *ab) 3143 { 3144 struct fwohci_pkt pkt; 3145 struct ieee1394_softc *sc = ab->ab_req; 3146 struct fwohci_softc *psc = 3147 (struct fwohci_softc *)sc->sc1394_dev.dv_parent; 3148 struct fwohci_cb *fcb; 3149 u_int32_t high, lo; 3150 int rv, tcode; 3151 3152 /* Have to have a callback when reading. */ 3153 if (ab->ab_cb == NULL) 3154 return -1; 3155 3156 fcb = malloc(sizeof(struct fwohci_cb), M_DEVBUF, M_WAITOK); 3157 fcb->ab = ab; 3158 fcb->count = 0; 3159 fcb->abuf_valid = 1; 3160 3161 high = ((ab->ab_addr & 0x0000ffff00000000) >> 32); 3162 lo = (ab->ab_addr & 0x00000000ffffffff); 3163 3164 memset(&pkt, 0, sizeof(pkt)); 3165 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3166 pkt.fp_hdr[2] = lo; 3167 pkt.fp_dlen = 0; 3168 3169 if (ab->ab_length == 4) { 3170 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 3171 tcode = IEEE1394_TCODE_READ_RESP_QUAD; 3172 pkt.fp_hlen = 12; 3173 } else { 3174 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_BLOCK; 3175 pkt.fp_hlen = 16; 3176 tcode = IEEE1394_TCODE_READ_RESP_BLOCK; 3177 pkt.fp_hdr[3] = (ab->ab_length << 16); 3178 } 3179 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) | 3180 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4); 3181 3182 pkt.fp_statusarg = fcb; 3183 pkt.fp_statuscb = fwohci_read_resp; 3184 3185 rv = fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id, 3186 psc->sc_tlabel, fwohci_read_resp, fcb); 3187 if (rv) 3188 return rv; 3189 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt); 3190 if (rv) 3191 fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id, 3192 psc->sc_tlabel, NULL, NULL); 3193 psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f; 3194 fcb->count = 1; 3195 return rv; 3196 } 3197 3198 static int 3199 fwohci_write(struct ieee1394_abuf *ab) 3200 { 3201 struct fwohci_pkt pkt; 3202 struct ieee1394_softc *sc = ab->ab_req; 3203 struct fwohci_softc *psc = 3204 (struct fwohci_softc *)sc->sc1394_dev.dv_parent; 3205 u_int32_t high, lo; 3206 int rv; 3207 3208 if (ab->ab_length > IEEE1394_MAX_REC(sc->sc1394_max_receive)) { 3209 DPRINTF(("Packet too large: %d\n", ab->ab_length)); 3210 return E2BIG; 3211 } 3212 3213 if (ab->ab_data && ab->ab_uio) 3214 panic("Can't call with uio and data set\n"); 3215 if ((ab->ab_data == NULL) && (ab->ab_uio == NULL)) 3216 panic("One of either ab_data or ab_uio must be set\n"); 3217 3218 memset(&pkt, 0, sizeof(pkt)); 3219 3220 pkt.fp_tcode = ab->ab_tcode; 3221 if (ab->ab_data) { 3222 pkt.fp_uio.uio_iov = pkt.fp_iov; 3223 pkt.fp_uio.uio_segflg = UIO_SYSSPACE; 3224 pkt.fp_uio.uio_rw = UIO_WRITE; 3225 } else 3226 memcpy(&pkt.fp_uio, ab->ab_uio, sizeof(struct uio)); 3227 3228 pkt.fp_statusarg = ab; 3229 pkt.fp_statuscb = fwohci_write_ack; 3230 3231 switch (ab->ab_tcode) { 3232 case IEEE1394_TCODE_WRITE_RESP: 3233 pkt.fp_hlen = 12; 3234 case IEEE1394_TCODE_READ_RESP_QUAD: 3235 case IEEE1394_TCODE_READ_RESP_BLOCK: 3236 if (!pkt.fp_hlen) 3237 pkt.fp_hlen = 16; 3238 high = ab->ab_retlen; 3239 ab->ab_retlen = 0; 3240 lo = 0; 3241 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) | 3242 (ab->ab_tlabel << 10) | (pkt.fp_tcode << 4); 3243 break; 3244 default: 3245 pkt.fp_hlen = 16; 3246 high = ((ab->ab_addr & 0x0000ffff00000000) >> 32); 3247 lo = (ab->ab_addr & 0x00000000ffffffff); 3248 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) | 3249 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4); 3250 break; 3251 } 3252 3253 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3254 pkt.fp_hdr[2] = lo; 3255 if (pkt.fp_hlen == 16) { 3256 if (ab->ab_length == 4) { 3257 pkt.fp_hdr[3] = ab->ab_data[0]; 3258 pkt.fp_dlen = 0; 3259 } else { 3260 pkt.fp_hdr[3] = (ab->ab_length << 16); 3261 pkt.fp_dlen = ab->ab_length; 3262 if (ab->ab_data) { 3263 pkt.fp_uio.uio_iovcnt = 1; 3264 pkt.fp_uio.uio_resid = ab->ab_length; 3265 pkt.fp_iov[0].iov_base = ab->ab_data; 3266 pkt.fp_iov[0].iov_len = ab->ab_length; 3267 } 3268 } 3269 } 3270 switch (ab->ab_tcode) { 3271 case IEEE1394_TCODE_WRITE_RESP: 3272 case IEEE1394_TCODE_READ_RESP_QUAD: 3273 case IEEE1394_TCODE_READ_RESP_BLOCK: 3274 rv = fwohci_at_output(psc, psc->sc_ctx_atrs, &pkt); 3275 break; 3276 default: 3277 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt); 3278 break; 3279 } 3280 return rv; 3281 } 3282 3283 static int 3284 fwohci_read_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 3285 { 3286 struct fwohci_cb *fcb = arg; 3287 struct ieee1394_abuf *ab = fcb->ab; 3288 struct fwohci_pkt newpkt; 3289 u_int32_t *cur, high, lo; 3290 int i, tcode, rcode, status, rv; 3291 3292 /* 3293 * Both the ACK handling and normal response callbacks are handled here. 3294 * The main reason for this is the various error conditions that can 3295 * occur trying to block read some areas and the ways that gets reported 3296 * back to calling station. This is a variety of ACK codes, responses, 3297 * etc which makes it much more difficult to process if both aren't 3298 * handled here. 3299 */ 3300 3301 /* Check for status packet. */ 3302 3303 if (pkt->fp_tcode == -1) { 3304 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK; 3305 rcode = -1; 3306 tcode = (pkt->fp_hdr[0] >> 4) & 0xf; 3307 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) && 3308 (status != OHCI_CTXCTL_EVENT_ACK_PENDING)) 3309 DPRINTFN(2, ("Got status packet: 0x%02x\n", 3310 (unsigned int)status)); 3311 fcb->count--; 3312 3313 /* 3314 * Got all the ack's back and the buffer is invalid (i.e. the 3315 * callback has been called. Clean up. 3316 */ 3317 3318 if (fcb->abuf_valid == 0) { 3319 if (fcb->count == 0) 3320 free(fcb, M_DEVBUF); 3321 return IEEE1394_RCODE_COMPLETE; 3322 } 3323 } else { 3324 status = -1; 3325 tcode = pkt->fp_tcode; 3326 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12; 3327 } 3328 3329 /* 3330 * Some area's (like the config rom want to be read as quadlets only. 3331 * 3332 * The current ideas to try are: 3333 * 3334 * Got an ACK_TYPE_ERROR on a block read. 3335 * 3336 * Got either RCODE_TYPE or RCODE_ADDRESS errors in a block read 3337 * response. 3338 * 3339 * In all cases construct a new packet for a quadlet read and let 3340 * mutli_resp handle the iteration over the space. 3341 */ 3342 3343 if (((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) && 3344 (tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) || 3345 (((rcode == IEEE1394_RCODE_TYPE_ERROR) || 3346 (rcode == IEEE1394_RCODE_ADDRESS_ERROR)) && 3347 (tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) { 3348 3349 /* Read the area in quadlet chunks (internally track this). */ 3350 3351 memset(&newpkt, 0, sizeof(newpkt)); 3352 3353 high = ((ab->ab_addr & 0x0000ffff00000000) >> 32); 3354 lo = (ab->ab_addr & 0x00000000ffffffff); 3355 3356 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 3357 newpkt.fp_hlen = 12; 3358 newpkt.fp_dlen = 0; 3359 newpkt.fp_hdr[1] = 3360 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3361 newpkt.fp_hdr[2] = lo; 3362 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 3363 (newpkt.fp_tcode << 4); 3364 3365 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, 3366 ab->ab_req->sc1394_node_id, sc->sc_tlabel, 3367 fwohci_read_multi_resp, fcb); 3368 if (rv) { 3369 (*ab->ab_cb)(ab, -1); 3370 goto cleanup; 3371 } 3372 newpkt.fp_statusarg = fcb; 3373 newpkt.fp_statuscb = fwohci_read_resp; 3374 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt); 3375 if (rv) { 3376 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, 3377 ab->ab_req->sc1394_node_id, sc->sc_tlabel, NULL, 3378 NULL); 3379 (*ab->ab_cb)(ab, -1); 3380 goto cleanup; 3381 } 3382 fcb->count++; 3383 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 3384 return IEEE1394_RCODE_COMPLETE; 3385 } else if ((rcode != -1) || ((status != -1) && 3386 (status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) && 3387 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))) { 3388 3389 /* 3390 * Recombine all the iov data into 1 chunk for higher 3391 * level code. 3392 */ 3393 3394 if (rcode != -1) { 3395 cur = ab->ab_data; 3396 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) { 3397 /* 3398 * Make sure and don't exceed the buffer 3399 * allocated for return. 3400 */ 3401 if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) > 3402 ab->ab_length) { 3403 memcpy(cur, pkt->fp_iov[i].iov_base, 3404 (ab->ab_length - ab->ab_retlen)); 3405 ab->ab_retlen = ab->ab_length; 3406 break; 3407 } 3408 memcpy(cur, pkt->fp_iov[i].iov_base, 3409 pkt->fp_iov[i].iov_len); 3410 cur += pkt->fp_iov[i].iov_len; 3411 ab->ab_retlen += pkt->fp_iov[i].iov_len; 3412 } 3413 } 3414 if (status != -1) 3415 /* XXX: Need a complete tlabel interface. */ 3416 for (i = 0; i < 64; i++) 3417 fwohci_handler_set(sc, 3418 IEEE1394_TCODE_READ_RESP_QUAD, 3419 ab->ab_req->sc1394_node_id, i, NULL, NULL); 3420 (*ab->ab_cb)(ab, rcode); 3421 goto cleanup; 3422 } else 3423 /* Good ack packet. */ 3424 return IEEE1394_RCODE_COMPLETE; 3425 3426 /* Can't get here unless ab->ab_cb has been called. */ 3427 3428 cleanup: 3429 fcb->abuf_valid = 0; 3430 if (fcb->count == 0) 3431 free(fcb, M_DEVBUF); 3432 return IEEE1394_RCODE_COMPLETE; 3433 } 3434 3435 static int 3436 fwohci_read_multi_resp(struct fwohci_softc *sc, void *arg, 3437 struct fwohci_pkt *pkt) 3438 { 3439 struct fwohci_cb *fcb = arg; 3440 struct ieee1394_abuf *ab = fcb->ab; 3441 struct fwohci_pkt newpkt; 3442 u_int32_t high, lo; 3443 int rcode, rv; 3444 3445 /* 3446 * Bad return codes from the wire, just return what's already in the 3447 * buf. 3448 */ 3449 3450 /* Make sure a response packet didn't arrive after a bad ACK. */ 3451 if (fcb->abuf_valid == 0) 3452 return IEEE1394_RCODE_COMPLETE; 3453 3454 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12; 3455 3456 if (rcode) { 3457 (*ab->ab_cb)(ab, rcode); 3458 goto cleanup; 3459 } 3460 3461 if ((ab->ab_retlen + pkt->fp_iov[0].iov_len) > ab->ab_length) { 3462 memcpy(((char *)ab->ab_data + ab->ab_retlen), 3463 pkt->fp_iov[0].iov_base, (ab->ab_length - ab->ab_retlen)); 3464 ab->ab_retlen = ab->ab_length; 3465 } else { 3466 memcpy(((char *)ab->ab_data + ab->ab_retlen), 3467 pkt->fp_iov[0].iov_base, 4); 3468 ab->ab_retlen += 4; 3469 } 3470 /* Still more, loop and read 4 more bytes. */ 3471 if (ab->ab_retlen < ab->ab_length) { 3472 memset(&newpkt, 0, sizeof(newpkt)); 3473 3474 high = ((ab->ab_addr & 0x0000ffff00000000) >> 32); 3475 lo = (ab->ab_addr & 0x00000000ffffffff) + ab->ab_retlen; 3476 3477 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 3478 newpkt.fp_hlen = 12; 3479 newpkt.fp_dlen = 0; 3480 newpkt.fp_hdr[1] = 3481 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3482 newpkt.fp_hdr[2] = lo; 3483 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 3484 (newpkt.fp_tcode << 4); 3485 3486 newpkt.fp_statusarg = fcb; 3487 newpkt.fp_statuscb = fwohci_read_resp; 3488 3489 /* 3490 * Bad return code. Just give up and return what's 3491 * come in now. 3492 */ 3493 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, 3494 ab->ab_req->sc1394_node_id, sc->sc_tlabel, 3495 fwohci_read_multi_resp, fcb); 3496 if (rv) 3497 (*ab->ab_cb)(ab, -1); 3498 else { 3499 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt); 3500 if (rv) { 3501 fwohci_handler_set(sc, 3502 IEEE1394_TCODE_READ_RESP_QUAD, 3503 ab->ab_req->sc1394_node_id, sc->sc_tlabel, 3504 NULL, NULL); 3505 (*ab->ab_cb)(ab, -1); 3506 } else { 3507 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 3508 fcb->count++; 3509 return IEEE1394_RCODE_COMPLETE; 3510 } 3511 } 3512 } else 3513 (*ab->ab_cb)(ab, IEEE1394_RCODE_COMPLETE); 3514 3515 cleanup: 3516 /* Can't get here unless ab_cb has been called. */ 3517 fcb->abuf_valid = 0; 3518 if (fcb->count == 0) 3519 free(fcb, M_DEVBUF); 3520 return IEEE1394_RCODE_COMPLETE; 3521 } 3522 3523 static int 3524 fwohci_write_ack(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 3525 { 3526 struct ieee1394_abuf *ab = arg; 3527 u_int16_t status; 3528 3529 3530 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK; 3531 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) && 3532 (status != OHCI_CTXCTL_EVENT_ACK_PENDING)) 3533 DPRINTF(("Got status packet: 0x%02x\n", 3534 (unsigned int)status)); 3535 3536 /* No callback means this level should free the buffers. */ 3537 if (ab->ab_cb) 3538 (*ab->ab_cb)(ab, status); 3539 else { 3540 if (ab->ab_data) 3541 free(ab->ab_data, M_1394DATA); 3542 free(ab, M_1394DATA); 3543 } 3544 return IEEE1394_RCODE_COMPLETE; 3545 } 3546 3547 static int 3548 fwohci_inreg(struct ieee1394_abuf *ab, int allow) 3549 { 3550 struct ieee1394_softc *sc = ab->ab_req; 3551 struct fwohci_softc *psc = 3552 (struct fwohci_softc *)sc->sc1394_dev.dv_parent; 3553 u_int32_t high, lo; 3554 int i, j, rv; 3555 3556 high = ((ab->ab_addr & 0x0000ffff00000000) >> 32); 3557 lo = (ab->ab_addr & 0x00000000ffffffff); 3558 3559 rv = 0; 3560 switch (ab->ab_tcode) { 3561 case IEEE1394_TCODE_READ_REQ_QUAD: 3562 case IEEE1394_TCODE_WRITE_REQ_QUAD: 3563 if (ab->ab_cb) 3564 rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo, 3565 fwohci_parse_input, ab); 3566 else 3567 fwohci_handler_set(psc, ab->ab_tcode, high, lo, NULL, 3568 NULL); 3569 break; 3570 case IEEE1394_TCODE_READ_REQ_BLOCK: 3571 case IEEE1394_TCODE_WRITE_REQ_BLOCK: 3572 if (allow) { 3573 for (i = 0; i < (ab->ab_length / 4); i++) { 3574 if (ab->ab_cb) { 3575 rv = fwohci_handler_set(psc, 3576 ab->ab_tcode, high, lo + (i * 4), 3577 fwohci_parse_input, ab); 3578 if (rv) 3579 break; 3580 } else 3581 fwohci_handler_set(psc, ab->ab_tcode, 3582 high, lo + (i * 4), NULL, NULL); 3583 } 3584 if (i != (ab->ab_length / 4)) { 3585 j = i + 1; 3586 for (i = 0; i < j; i++) 3587 fwohci_handler_set(psc, ab->ab_tcode, 3588 high, lo + (i * 4), NULL, NULL); 3589 } 3590 /* 3591 * XXX: Need something to indicate writing a smaller 3592 * amount is ok. 3593 */ 3594 if (ab->ab_cb) 3595 ab->ab_data = (void *)1; 3596 } else { 3597 if (ab->ab_cb) 3598 rv = fwohci_handler_set(psc, ab->ab_tcode, high, 3599 lo, fwohci_parse_input, ab); 3600 else 3601 fwohci_handler_set(psc, ab->ab_tcode, high, lo, 3602 NULL, NULL); 3603 } 3604 break; 3605 default: 3606 DPRINTF(("Invalid registration tcode: %d\n", ab->ab_tcode)); 3607 return -1; 3608 break; 3609 } 3610 return rv; 3611 } 3612 3613 static int 3614 fwohci_unreg(struct ieee1394_abuf *ab, int allow) 3615 { 3616 void *save; 3617 int rv; 3618 3619 save = ab->ab_cb; 3620 ab->ab_cb = NULL; 3621 rv = fwohci_inreg(ab, allow); 3622 ab->ab_cb = save; 3623 return rv; 3624 } 3625 3626 static int 3627 fwohci_parse_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 3628 { 3629 struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg; 3630 u_int64_t addr; 3631 u_int32_t *cur; 3632 int i, count; 3633 3634 ab->ab_tcode = (pkt->fp_hdr[0] >> 4) & 0xf; 3635 ab->ab_tlabel = (pkt->fp_hdr[0] >> 10) & 0x3f; 3636 addr = (((u_int64_t)(pkt->fp_hdr[1] & 0xffff) << 32) | pkt->fp_hdr[2]); 3637 3638 switch (ab->ab_tcode) { 3639 case IEEE1394_TCODE_READ_REQ_QUAD: 3640 ab->ab_retlen = 4; 3641 break; 3642 case IEEE1394_TCODE_READ_REQ_BLOCK: 3643 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff; 3644 if (ab->ab_data) { 3645 if ((addr + ab->ab_retlen) > 3646 (ab->ab_addr + ab->ab_length)) 3647 return IEEE1394_RCODE_ADDRESS_ERROR; 3648 ab->ab_data = NULL; 3649 } else 3650 if (ab->ab_retlen != ab->ab_length) 3651 return IEEE1394_RCODE_ADDRESS_ERROR; 3652 break; 3653 case IEEE1394_TCODE_WRITE_REQ_QUAD: 3654 ab->ab_retlen = 4; 3655 case IEEE1394_TCODE_WRITE_REQ_BLOCK: 3656 if (!ab->ab_retlen) 3657 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff; 3658 if (ab->ab_data) { 3659 if ((addr + ab->ab_retlen) > 3660 (ab->ab_addr + ab->ab_length)) 3661 return IEEE1394_RCODE_ADDRESS_ERROR; 3662 ab->ab_data = NULL; 3663 } else 3664 if (ab->ab_retlen != ab->ab_length) 3665 return IEEE1394_RCODE_ADDRESS_ERROR; 3666 3667 ab->ab_data = malloc(ab->ab_retlen, M_1394DATA, M_WAITOK); 3668 if (ab->ab_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) 3669 ab->ab_data[0] = pkt->fp_hdr[3]; 3670 else { 3671 count = 0; 3672 cur = ab->ab_data; 3673 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) { 3674 memcpy(cur, pkt->fp_iov[i].iov_base, 3675 pkt->fp_iov[i].iov_len); 3676 cur += pkt->fp_iov[i].iov_len; 3677 count += pkt->fp_iov[i].iov_len; 3678 } 3679 if (ab->ab_retlen != count) 3680 panic("Packet claims %d length " 3681 "but only %d bytes returned\n", 3682 ab->ab_retlen, count); 3683 } 3684 break; 3685 default: 3686 panic("Got a callback for a tcode that wasn't requested: %d\n", 3687 ab->ab_tcode); 3688 break; 3689 } 3690 ab->ab_addr = addr; 3691 ab->ab_cb(ab, IEEE1394_RCODE_COMPLETE); 3692 return -1; 3693 } 3694 3695 static int 3696 fwohci_submatch(struct device *parent, struct cfdata *cf, void *aux) 3697 { 3698 struct ieee1394_attach_args *fwa = aux; 3699 3700 /* Both halves must be filled in for a match. */ 3701 if ((cf->fwbuscf_idhi == FWBUS_UNK_IDHI && 3702 cf->fwbuscf_idlo == FWBUS_UNK_IDLO) || 3703 (cf->fwbuscf_idhi == ntohl(*((u_int32_t *)&fwa->uid[0])) && 3704 cf->fwbuscf_idlo == ntohl(*((u_int32_t *)&fwa->uid[4])))) 3705 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 3706 return 0; 3707 } 3708 3709 int 3710 fwohci_detach(struct fwohci_softc *sc, int flags) 3711 { 3712 int rv = 0; 3713 3714 if (sc->sc_sc1394.sc1394_if != NULL) 3715 rv = config_detach(sc->sc_sc1394.sc1394_if, flags); 3716 if (rv != 0) 3717 return (rv); 3718 3719 callout_stop(&sc->sc_selfid_callout); 3720 3721 if (sc->sc_powerhook != NULL) 3722 powerhook_disestablish(sc->sc_powerhook); 3723 if (sc->sc_shutdownhook != NULL) 3724 shutdownhook_disestablish(sc->sc_shutdownhook); 3725 3726 return (rv); 3727 } 3728 3729 int 3730 fwohci_activate(struct device *self, enum devact act) 3731 { 3732 struct fwohci_softc *sc = (struct fwohci_softc *)self; 3733 int s, rv = 0; 3734 3735 s = splhigh(); 3736 switch (act) { 3737 case DVACT_ACTIVATE: 3738 rv = EOPNOTSUPP; 3739 break; 3740 3741 case DVACT_DEACTIVATE: 3742 if (sc->sc_sc1394.sc1394_if != NULL) 3743 rv = config_deactivate(sc->sc_sc1394.sc1394_if); 3744 break; 3745 } 3746 splx(s); 3747 3748 return (rv); 3749 } 3750 3751 #ifdef FW_DEBUG 3752 static void 3753 fwohci_show_intr(struct fwohci_softc *sc, u_int32_t intmask) 3754 { 3755 3756 printf("%s: intmask=0x%08x:", sc->sc_sc1394.sc1394_dev.dv_xname, 3757 intmask); 3758 if (intmask & OHCI_Int_CycleTooLong) 3759 printf(" CycleTooLong"); 3760 if (intmask & OHCI_Int_UnrecoverableError) 3761 printf(" UnrecoverableError"); 3762 if (intmask & OHCI_Int_CycleInconsistent) 3763 printf(" CycleInconsistent"); 3764 if (intmask & OHCI_Int_BusReset) 3765 printf(" BusReset"); 3766 if (intmask & OHCI_Int_SelfIDComplete) 3767 printf(" SelfIDComplete"); 3768 if (intmask & OHCI_Int_LockRespErr) 3769 printf(" LockRespErr"); 3770 if (intmask & OHCI_Int_PostedWriteErr) 3771 printf(" PostedWriteErr"); 3772 if (intmask & OHCI_Int_ReqTxComplete) 3773 printf(" ReqTxComplete(0x%04x)", 3774 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST, 3775 OHCI_SUBREG_ContextControlClear)); 3776 if (intmask & OHCI_Int_RespTxComplete) 3777 printf(" RespTxComplete(0x%04x)", 3778 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE, 3779 OHCI_SUBREG_ContextControlClear)); 3780 if (intmask & OHCI_Int_ARRS) 3781 printf(" ARRS(0x%04x)", 3782 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE, 3783 OHCI_SUBREG_ContextControlClear)); 3784 if (intmask & OHCI_Int_ARRQ) 3785 printf(" ARRQ(0x%04x)", 3786 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST, 3787 OHCI_SUBREG_ContextControlClear)); 3788 if (intmask & OHCI_Int_IsochRx) 3789 printf(" IsochRx(0x%08x)", 3790 OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear)); 3791 if (intmask & OHCI_Int_IsochTx) 3792 printf(" IsochTx(0x%08x)", 3793 OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear)); 3794 if (intmask & OHCI_Int_RQPkt) 3795 printf(" RQPkt(0x%04x)", 3796 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST, 3797 OHCI_SUBREG_ContextControlClear)); 3798 if (intmask & OHCI_Int_RSPkt) 3799 printf(" RSPkt(0x%04x)", 3800 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE, 3801 OHCI_SUBREG_ContextControlClear)); 3802 printf("\n"); 3803 } 3804 3805 static void 3806 fwohci_show_phypkt(struct fwohci_softc *sc, u_int32_t val) 3807 { 3808 u_int8_t key, phyid; 3809 3810 key = (val & 0xc0000000) >> 30; 3811 phyid = (val & 0x3f000000) >> 24; 3812 printf("%s: PHY packet from %d: ", 3813 sc->sc_sc1394.sc1394_dev.dv_xname, phyid); 3814 switch (key) { 3815 case 0: 3816 printf("PHY Config:"); 3817 if (val & 0x00800000) 3818 printf(" ForceRoot"); 3819 if (val & 0x00400000) 3820 printf(" Gap=%x", (val & 0x003f0000) >> 16); 3821 printf("\n"); 3822 break; 3823 case 1: 3824 printf("Link-on\n"); 3825 break; 3826 case 2: 3827 printf("SelfID:"); 3828 if (val & 0x00800000) { 3829 printf(" #%d", (val & 0x00700000) >> 20); 3830 } else { 3831 if (val & 0x00400000) 3832 printf(" LinkActive"); 3833 printf(" Gap=%x", (val & 0x003f0000) >> 16); 3834 printf(" Spd=S%d", 100 << ((val & 0x0000c000) >> 14)); 3835 if (val & 0x00000800) 3836 printf(" Cont"); 3837 if (val & 0x00000002) 3838 printf(" InitiateBusReset"); 3839 } 3840 if (val & 0x00000001) 3841 printf(" +"); 3842 printf("\n"); 3843 break; 3844 default: 3845 printf("unknown: 0x%08x\n", val); 3846 break; 3847 } 3848 } 3849 #endif /* FW_DEBUG */ 3850