⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ohci1394.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -