📄 ohci1394.c
字号:
} else { d->prg_cpu[i]->branchAddress = cpu_to_le32((d->prg_bus[0] & 0xfffffff0)); //Z:0,last descriptor,see pdf_doc,p96 } d->prg_cpu[i]->address = cpu_to_le32(d->buf_bus[i]); d->prg_cpu[i]->status = cpu_to_le32(d->buf_size); } d->buf_ind = 0; d->buf_offset = 0; if (d->type == DMA_CTX_ISO) { /* Clear contextControl */ reg_write(ohci, d->ctrlClear, 0xffffffff); /* Set bufferFill, isochHeader, multichannel for IR context */ reg_write(ohci, d->ctrlSet, 0xd0000000); /* Set the context match register to match on all tags */ reg_write(ohci, d->ctxtMatch, 0xf0000000); /* Clear the multi channel mask high and low registers */ //OHCI1394_IRMultiChanMaskHiClear:0x74,see pdf_doc,p141 reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); //OHCI1394_IRMultiChanMaskLoClear:0x7C,see pdf_doc,p142 reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); /* Set up isoRecvIntMask to generate interrupts */ //OHCI1394_IsoRecvIntMaskSet:0xA8,see pdf_doc,p68 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx); } /* Tell the controller where the first AR program is */ reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1); //see 0x1CC,p97 /* Run context */ reg_write(ohci, d->ctrlSet, 0x00008000); DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx);}/* Initialize the dma transmit context */static void initialize_dma_trm_ctx(struct dma_trm_ctx *d){ struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); /* Stop the context */ ohci1394_stop_context(ohci, d->ctrlClear, NULL); d->prg_ind = 0; d->sent_ind = 0; d->free_prgs = d->num_desc; d->branchAddrPtr = NULL; INIT_LIST_HEAD(&d->fifo_list); INIT_LIST_HEAD(&d->pending_list); if (d->type == DMA_CTX_ISO) { /* enable interrupts */ //OHCI1394_IsoXmitIntMaskSet:0x98,see pdf_doc,p67 reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx); } DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx);}/* Count the number of available iso contexts *///called by: ohci1394_pci_probe()//see pdf_doc,p67,p68static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg){ int i,ctx=0; u32 tmp; reg_write(ohci, reg, 0xffffffff); tmp = reg_read(ohci, reg); DBGMSG(ohci->id,"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;}static void ohci_init_config_rom(struct ti_ohci *ohci);/* Global initialization */static void ohci_initialize(struct ti_ohci *ohci){ char irq_buf[16]; quadlet_t buf; spin_lock_init(&ohci->phy_reg_lock); spin_lock_init(&ohci->event_lock); /* Put some defaults to these undefined bus options */ //OHCI1394_BusOptions:0x20,see pdf_doc p41, //IRMC,CMC and ISC,cyc_clk_acc,PMC and BMC: ???,not documented buf = reg_read(ohci, OHCI1394_BusOptions); buf |= 0xE0000000; /* Enable IRMC, CMC and ISC */ 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 */ //OHCI1394_NodeID:0xE8,see pdf_doc,p53 //set bus number 0xffc0,nodenumber 0. reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); /* Enable posted writes */ //OHCI1394_HCControlSet,0x50,see pdf_doc,p45,47 reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable); /* Clear link control register */ //OHCI1394_LinkControlClear:0xE4,see pdf_doc,p51 reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); /* Enable cycle timer and cycle master and set the IRM * contender bit in our self ID packets. */ //OHCI1394_LinkControlSet:0xE0,see pdf_doc,p51 reg_write(ohci, OHCI1394_LinkControlSet, 0x00300000); //address:4, data:0xc0 set_phy_reg_mask(ohci, 4, 0xc0); /* Clear interrupt registers */ //OHCI1394_IntMaskClear:0x8C,see pdf_doc,p65 reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); //OHCI1394_IntEventClear:0x84,see pdf_doc,p62 reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); /* Set up self-id dma buffer */ //OHCI1394_SelfIDBuffer:0x64,see pdf_doc,p147 reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus); /* enable self-id dma */ //OHCI1394_LinkControlSet:0xE0,see pdf_doc,p51,accept self_ID packets reg_write(ohci, OHCI1394_LinkControlSet, 0x00000200); /* Set the Config ROM mapping register */ //OHCI1394_ConfigROMmap:0x34,see pdf_doc,p44 reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus); /* Initialize the Config ROM */ ohci_init_config_rom(ohci); /* Now get our max packet size */ //OHCI1394_BusOptions:0x20,see pdf_doc,p41 ohci->max_packet_size = 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); /* Don't accept phy packets into AR request context */ //OHCI1394_LinkControlClear:0xE4,see pdf_doc,p51 reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); /* Clear the interrupt mask */ //OHCI1394_IsoRecvIntMaskClear:0xAC,see pdf_doc,p68 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); //OHCI1394_IsoRecvIntEventClear:0xA4,see pdf_doc,p68 reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); /* Clear the interrupt mask */ //OHCI1394_IsoXmitIntMaskClear:0x9C,see pdf_doc,p67 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); //OHCI1394_IsoXmitIntEventClear:0x94,see pdf_doc,p66 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); /* * Accept AT requests from all nodes. This probably * will have to be controlled from the subsystem * on a per node basis. */ //OHCI1394_AsReqFilterHiSet:0x100,see pdf_doc,p56 reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000); /* Specify AT retries */ //OHCI1394_ATRetries:0x08,see pdf_doc,p37 reg_write(ohci, OHCI1394_ATRetries, OHCI1394_MAX_AT_REQ_RETRIES | //OHCI1394_MAX_AT_REQ_RETRIES:0x2 (OHCI1394_MAX_AT_RESP_RETRIES<<4) | //OHCI1394_MAX_AT_RESP_RETRIES:0x02 (OHCI1394_MAX_PHYS_RESP_RETRIES<<8)); //OHCI1394_MAX_PHYS_RESP_RETRIES:0x08 /* We don't want hardware swapping */ //OHCI1394_HCControlClear:0x54,see pdf_doc,p45 reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap); //0x40000000 /* Enable interrupts */ //OHCI1394_IntMaskSet:0x88,see pdf_doc,p65 reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_unrecoverableError | //0x01000000 OHCI1394_masterIntEnable | //0x80000000 OHCI1394_busReset | //0x00020000 OHCI1394_selfIDComplete | //0x00010000 OHCI1394_RSPkt | //0x00000020 OHCI1394_RQPkt | //0x00000010 OHCI1394_respTxComplete | //0x00000002 OHCI1394_reqTxComplete | //0x00000001 OHCI1394_isochRx | //0x00000080 OHCI1394_isochTx | //0x00000040 OHCI1394_cycleInconsistent); //0x00800000 /* Enable link */ //OHCI1394_HCControlSet:0x50,see pdf_doc,p45 reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); //0x00020000 //OHCI1394_Version:0x00,see pdf_doc,p35 buf = reg_read(ohci, OHCI1394_Version);#ifndef __sparc__ sprintf (irq_buf, "%d", ohci->dev->irq);#else sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));#endif PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " "MMIO=[%lx-%lx] Max Packet=[%d]", ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf, pci_resource_start(ohci->dev, 0), pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, ohci->max_packet_size);}/* * 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.*///called by: dma_trm_flush()//struct ti_ohci,struct dma_trm_ctx: see ohci1394.h//struct hpsb_packet: see ieee1394_core.hstatic void insert_packet(struct ti_ohci *ohci, struct dma_trm_ctx *d, struct hpsb_packet *packet){ u32 cycleTimer; int idx = d->prg_ind; DBGMSG(ohci->id, "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 */ //OHCI1394_IsochronousCycleTimer:0xF0,see pdf_doc,p55 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(ohci->id, "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); //OHCI1394_TCODE_PHY:0xE 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 | //see pdf_doc,p84,AT Data Format (packet->header[0] & 0xFFFF); if (packet->tcode == TCODE_ISO_DATA) { //TCODE_ISO_DATA:0xA,ieee1394.h /* 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]; } packet_swab(d->prg_cpu[idx]->data, packet->tcode); } if (packet->data_size) { /* block transmit */ if (packet->tcode == TCODE_STREAM_DATA){ //0xA d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE | //0x00000000,see pdf_doc,p70 DMA_CTL_IMMEDIATE | 0x8); //0x02000000(key),see pdf_doc,p71=>OUTPUT_MORE_IMMEDIATE } else { d->prg_cpu[idx]->begin.control = // = OUTPUT_MORE_IMMEDIATE,see pdf_doc,p71 cpu_to_le32(DMA_CTL_OUTPUT_MORE | //0x00000000,see pdf_doc,p70 DMA_CTL_IMMEDIATE | 0x10); //0x02000000(key),see pdf_doc,p71 } d->prg_cpu[idx]->end.control = // = OUTPUT_MORE_IMMEDIATE,see pdf_doc,p71 cpu_to_le32(DMA_CTL_OUTPUT_LAST | //0x10000000,see pdf_doc,p72 DMA_CTL_IRQ | //0x00300000, DMA_CTL_BRANCH | //0x000c0000 packet->data_size); /* * Check that the packet data buffer * does not cross a page boundary. */ if (cross_bound((unsigned long)packet->data, packet->data_size)>0) { /* FIXME: do something about it */ PRINT(KERN_ERR, ohci->id, "%s: packet data addr: %p size %Zd bytes " "cross page boundary", __FUNCTION__, packet->data, 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, 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 | //0x10000000,see pdf_doc,p72 DMA_CTL_IMMEDIATE | //0x02000000(key),see pdf_doc,p71 DMA_CTL_IRQ | //0x00300000, DMA_CTL_BRANCH | //0x000c0000 (packet->header_size + 4)); else d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | //0x10000000,see pdf_doc,p72 DMA_CTL_IMMEDIATE | //0x02000000(key),see pdf_doc,p71 DMA_CTL_IRQ | //0x00300000, DMA_CTL_BRANCH | //0x000c0000 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 | //see pdf_doc,p126,IT Data Format (packet->header[0] & 0xFFFF); d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; packet_swab(d->prg_cpu[idx]->data, packet->tcode); d->prg_cpu[idx]->begin.control = //= OUTPUT_MORE_IMMEDIATE,see pdf_doc,p113 cpu_to_le32(DMA_CTL_OUTPUT_MORE | //0x00000000, DMA_CTL_IMMEDIATE | 0x8); //0x02000000, d->prg_cpu[idx]->end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | //0x10000000,see pdf_doc,p114 DMA_CTL_UPDATE | //0x08000000 DMA_CTL_IRQ | //0x00300000 DMA_CTL_BRANCH | //0x000c0000 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(ohci->id, "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.*/ //called by: ohci_transmit(),dma_trm_tasklet()//struct ti_ohci,struct dma_trm_ctx: see ohci1394.h//struct hpsb_packet: see ieee1394_core.hstatic int dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d){ struct hpsb_packet *p; int idx,z; if (list_empty(&d->pending_list) || d->free_prgs == 0) return 0; p = driver_packet(d->pending_list.next); idx = d->prg_ind; z = (p->data_size) ? 3 : 2; /* insert the packets into the dma fifo */ while (d->free_prgs > 0 && !list_empty(&d->pending_list)) { struct hpsb_packet *p = driver_packet(d->pending_list.next); list_del(&p->driver_list); insert_packet(ohci, d, p); } if (d->free_prgs == 0) DBGMSG(ohci->id, "Transmit DMA FIFO ctx=%d is full... waiting", d->ctx); /* Is the context running ? (should be unless it is the first packet to be sent in this context) */ //OHCI1394_IsoRcvContextControlSet:0x400,see pdf_doc,138 if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { //may see pdf_doc,p80,p119
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -