📄 ohci1394.c
字号:
DBGMSG("Iso contexts reg: %08x implemented: %08x", reg, tmp); /* Count the number of contexts */ for (i=0; i<32; i++) { if (tmp & 1) ctx++; tmp >>= 1; } return ctx;}/* Global initialization */static void ohci_initialize(struct ti_ohci *ohci){ quadlet_t buf; int num_ports, i; spin_lock_init(&ohci->phy_reg_lock); /* Put some defaults to these undefined bus options */ buf = reg_read(ohci, OHCI1394_BusOptions); buf |= 0x60000000; /* Enable CMC and ISC */ if (hpsb_disable_irm) buf &= ~0x80000000; else buf |= 0x80000000; /* Enable IRMC */ buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */ buf &= ~0x18000000; /* Disable PMC and BMC */ reg_write(ohci, OHCI1394_BusOptions, buf); /* Set the bus number */ reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); /* Enable posted writes */ reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable); /* Clear link control register */ reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); /* Enable cycle timer and cycle master and set the IRM * contender bit in our self ID packets if appropriate. */ reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable | OHCI1394_LinkControl_CycleMaster); i = get_phy_reg(ohci, 4) | PHY_04_LCTRL; if (hpsb_disable_irm) i &= ~PHY_04_CONTENDER; else i |= PHY_04_CONTENDER; set_phy_reg(ohci, 4, i); /* Set up self-id dma buffer */ reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus); /* enable self-id and phys */ reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID | OHCI1394_LinkControl_RcvPhyPkt); /* Set the Config ROM mapping register */ reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus); /* Now get our max packet size */ ohci->max_packet_size = 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); /* Clear the interrupt mask */ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); /* Clear the interrupt mask */ reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); /* Initialize AR dma */ initialize_dma_rcv_ctx(&ohci->ar_req_context, 0); initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0); /* Initialize AT dma */ initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_resp_context); /* Initialize IR Legacy DMA channel mask */ ohci->ir_legacy_channels = 0; /* Accept AR requests from all nodes */ reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); /* Set the address range of the physical response unit. * Most controllers do not implement it as a writable register though. * They will keep a hardwired offset of 0x00010000 and show 0x0 as * register content. * To actually enable physical responses is the job of our interrupt * handler which programs the physical request filter. */ reg_write(ohci, OHCI1394_PhyUpperBound, OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED >> 16); DBGMSG("physUpperBoundOffset=%08x", reg_read(ohci, OHCI1394_PhyUpperBound)); /* Specify AT retries */ reg_write(ohci, OHCI1394_ATRetries, OHCI1394_MAX_AT_REQ_RETRIES | (OHCI1394_MAX_AT_RESP_RETRIES<<4) | (OHCI1394_MAX_PHYS_RESP_RETRIES<<8)); /* We don't want hardware swapping */ reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap); /* Enable interrupts */ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_unrecoverableError | OHCI1394_masterIntEnable | OHCI1394_busReset | OHCI1394_selfIDComplete | OHCI1394_RSPkt | OHCI1394_RQPkt | OHCI1394_respTxComplete | OHCI1394_reqTxComplete | OHCI1394_isochRx | OHCI1394_isochTx | OHCI1394_postedWriteErr | OHCI1394_cycleTooLong | OHCI1394_cycleInconsistent); /* Enable link */ reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); buf = reg_read(ohci, OHCI1394_Version); PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " "MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]", ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq, (unsigned long long)pci_resource_start(ohci->dev, 0), (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, ohci->max_packet_size, ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx); /* Check all of our ports to make sure that if anything is * connected, we enable that port. */ num_ports = get_phy_reg(ohci, 2) & 0xf; for (i = 0; i < num_ports; i++) { unsigned int status; set_phy_reg(ohci, 7, i); status = get_phy_reg(ohci, 8); if (status & 0x20) set_phy_reg(ohci, 8, status & ~1); } /* Serial EEPROM Sanity check. */ if ((ohci->max_packet_size < 512) || (ohci->max_packet_size > 4096)) { /* Serial EEPROM contents are suspect, set a sane max packet * size and print the raw contents for bug reports if verbose * debug is enabled. */#ifdef CONFIG_IEEE1394_VERBOSEDEBUG int i;#endif PRINT(KERN_DEBUG, "Serial EEPROM has suspicious values, " "attempting to setting max_packet_size to 512 bytes"); reg_write(ohci, OHCI1394_BusOptions, (reg_read(ohci, OHCI1394_BusOptions) & 0xf007) | 0x8002); ohci->max_packet_size = 512;#ifdef CONFIG_IEEE1394_VERBOSEDEBUG PRINT(KERN_DEBUG, " EEPROM Present: %d", (reg_read(ohci, OHCI1394_Version) >> 24) & 0x1); reg_write(ohci, OHCI1394_GUID_ROM, 0x80000000); for (i = 0; ((i < 1000) && (reg_read(ohci, OHCI1394_GUID_ROM) & 0x80000000)); i++) udelay(10); for (i = 0; i < 0x20; i++) { reg_write(ohci, OHCI1394_GUID_ROM, 0x02000000); PRINT(KERN_DEBUG, " EEPROM %02x: %02x", i, (reg_read(ohci, OHCI1394_GUID_ROM) >> 16) & 0xff); }#endif }}/* * Insert a packet in the DMA fifo and generate the DMA prg * FIXME: rewrite the program in order to accept packets crossing * page boundaries. * check also that a single dma descriptor doesn't cross a * page boundary. */static void insert_packet(struct ti_ohci *ohci, struct dma_trm_ctx *d, struct hpsb_packet *packet){ u32 cycleTimer; int idx = d->prg_ind; DBGMSG("Inserting packet for node " NODE_BUS_FMT ", tlabel=%d, tcode=0x%x, speed=%d", NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel, packet->tcode, packet->speed_code); d->prg_cpu[idx]->begin.address = 0; d->prg_cpu[idx]->begin.branchAddress = 0; if (d->type == DMA_CTX_ASYNC_RESP) { /* * For response packets, we need to put a timeout value in * the 16 lower bits of the status... let's try 1 sec timeout */ cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer); d->prg_cpu[idx]->begin.status = cpu_to_le32( (((((cycleTimer>>25)&0x7)+1)&0x7)<<13) | ((cycleTimer&0x01fff000)>>12)); DBGMSG("cycleTimer: %08x timeStamp: %08x", cycleTimer, d->prg_cpu[idx]->begin.status); } else d->prg_cpu[idx]->begin.status = 0; if ( (packet->type == hpsb_async) || (packet->type == hpsb_raw) ) { if (packet->type == hpsb_raw) { d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4); d->prg_cpu[idx]->data[1] = cpu_to_le32(packet->header[0]); d->prg_cpu[idx]->data[2] = cpu_to_le32(packet->header[1]); } else { d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | (packet->header[0] & 0xFFFF); if (packet->tcode == TCODE_ISO_DATA) { /* Sending an async stream packet */ d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; } else { /* Sending a normal async request or response */ d->prg_cpu[idx]->data[1] = (packet->header[1] & 0xFFFF) | (packet->header[0] & 0xFFFF0000); d->prg_cpu[idx]->data[2] = packet->header[2]; d->prg_cpu[idx]->data[3] = packet->header[3]; } header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode); } if (packet->data_size) { /* block transmit */ if (packet->tcode == TCODE_STREAM_DATA){ d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE | DMA_CTL_IMMEDIATE | 0x8); } else { d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE | DMA_CTL_IMMEDIATE | 0x10); } d->prg_cpu[idx]->end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_IRQ | DMA_CTL_BRANCH | packet->data_size); /* * Check that the packet data buffer * does not cross a page boundary. * * XXX Fix this some day. eth1394 seems to trigger * it, but ignoring it doesn't seem to cause a * problem. */#if 0 if (cross_bound((unsigned long)packet->data, packet->data_size)>0) { /* FIXME: do something about it */ PRINT(KERN_ERR, "%s: packet data addr: %p size %Zd bytes " "cross page boundary", __FUNCTION__, packet->data, packet->data_size); }#endif d->prg_cpu[idx]->end.address = cpu_to_le32( pci_map_single(ohci->dev, packet->data, packet->data_size, PCI_DMA_TODEVICE)); OHCI_DMA_ALLOC("single, block transmit packet"); d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.status = 0; if (d->branchAddrPtr) *(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x3); d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress); } else { /* quadlet transmit */ if (packet->type == hpsb_raw) d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_IMMEDIATE | DMA_CTL_IRQ | DMA_CTL_BRANCH | (packet->header_size + 4)); else d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_IMMEDIATE | DMA_CTL_IRQ | DMA_CTL_BRANCH | packet->header_size); if (d->branchAddrPtr) *(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x2); d->branchAddrPtr = &(d->prg_cpu[idx]->begin.branchAddress); } } else { /* iso packet */ d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | (packet->header[0] & 0xFFFF); d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode); d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE | DMA_CTL_IMMEDIATE | 0x8); d->prg_cpu[idx]->end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_UPDATE | DMA_CTL_IRQ | DMA_CTL_BRANCH | packet->data_size); d->prg_cpu[idx]->end.address = cpu_to_le32( pci_map_single(ohci->dev, packet->data, packet->data_size, PCI_DMA_TODEVICE)); OHCI_DMA_ALLOC("single, iso transmit packet"); d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.status = 0; DBGMSG("Iso xmit context info: header[%08x %08x]\n" " begin=%08x %08x %08x %08x\n" " %08x %08x %08x %08x\n" " end =%08x %08x %08x %08x", d->prg_cpu[idx]->data[0], d->prg_cpu[idx]->data[1], d->prg_cpu[idx]->begin.control, d->prg_cpu[idx]->begin.address, d->prg_cpu[idx]->begin.branchAddress, d->prg_cpu[idx]->begin.status, d->prg_cpu[idx]->data[0], d->prg_cpu[idx]->data[1], d->prg_cpu[idx]->data[2], d->prg_cpu[idx]->data[3], d->prg_cpu[idx]->end.control, d->prg_cpu[idx]->end.address, d->prg_cpu[idx]->end.branchAddress, d->prg_cpu[idx]->end.status); if (d->branchAddrPtr) *(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x3); d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress); } d->free_prgs--; /* queue the packet in the appropriate context queue */ list_add_tail(&packet->driver_list, &d->fifo_list); d->prg_ind = (d->prg_ind + 1) % d->num_desc;}/* * This function fills the FIFO with the (eventual) pending packets * and runs or wakes up the DMA prg if necessary. * * The function MUST be called with the d->lock held. */static void dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d){ struct hpsb_packet *packet, *ptmp; int idx = d->prg_ind; int z = 0; /* insert the packets into the dma fifo */ list_for_each_entry_safe(packet, ptmp, &d->pending_list, driver_list) { if (!d->free_prgs) break; /* For the first packet only */ if (!z) z = (packet->data_size) ? 3 : 2; /* Insert the packet */ list_del_init(&packet->driver_list); insert_packet(ohci, d, packet); } /* Nothing must have been done, either no free_prgs or no packets */ if (z == 0) return; /* Is the context running ? (should be unless it is the first packet to be sent in this context) */ if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { u32 nodeId = reg_read(ohci, OHCI1394_NodeID); DBGMSG("Starting transmit DMA ctx=%d",d->ctx); reg_write(ohci, d->cmdPtr, d->prg_bus[idx] | z); /* Check that the node id is valid, and not 63 */ if (!(nodeId & 0x80000000) || (nodeId & 0x3f) == 63) PRINT(KERN_ERR, "Running dma failed because Node ID is not valid"); else reg_write(ohci, d->ctrlSet, 0x8000); } else { /* Wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) DBGMSG("Waking transmit DMA ctx=%d",d->ctx); /* do this always, to avoid race condition */ reg_write(ohci, d->ctrlSet, 0x1000); } return;}/* Transmission of an async or iso packet */static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet){ struct ti_ohci *ohci = host->hostdata; struct dma_trm_ctx *d; unsigned long flags; if (packet->data_size > ohci->max_packet_size) { PRINT(KERN_ERR, "Transmit packet size %Zd is too big", packet->data_size); return -EOVERFLOW; } /* Decide whether we have an iso, a request, or a response packet */ if (packet->type == hpsb_raw) d = &ohci->at_req_context; else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) { /* The legacy IT DMA context is initialized on first * use. However, the alloc cannot be run from * interrupt context, so we bail out if that is the * case. I don't see anyone sending ISO packets from * interrupt context anyway... */ if (ohci->it_legacy_context.ohci == NULL) { if (in_interrupt()) { PRINT(KERN_ERR, "legacy IT context cannot be initialized during interrupt"); return -EINVAL; } if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context, DMA_CTX_ISO, 0, IT_NUM_DESC, OHCI1394_IsoXmitContextBase) < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -