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

📄 pcilynx.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
        lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */        lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */        lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */        /* lsid |= 1 << 11; *//* set contender (hack) */        lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */        for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */                if (phyreg[3 + i] & 0x4) {                        lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3)                                << (6 - i*2);                } else {                        lsid |= 1 << (6 - i*2);                }        }        cpu_to_be32s(&lsid);        PRINT(KERN_DEBUG, lynx->id, "generated own selfid 0x%x", lsid);        return lsid;}static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host){        quadlet_t *q = lynx->rcv_page;        int phyid, isroot, size;        quadlet_t lsid = 0;        int i;        if (lynx->phy_reg0 == -1 || lynx->selfid_size == -1) return;        size = lynx->selfid_size;        phyid = lynx->phy_reg0;        i = (size > 16 ? 16 : size) / 4 - 1;        while (i >= 0) {                cpu_to_be32s(&q[i]);                i--;        }                if (!lynx->phyic.reg_1394a) {                lsid = generate_own_selfid(lynx, host);        }        isroot = (phyid & 2) != 0;        phyid >>= 2;        PRINT(KERN_INFO, lynx->id, "SelfID process finished (phyid %d, %s)",              phyid, (isroot ? "root" : "not root"));        reg_write(lynx, LINK_ID, (0xffc0 | phyid) << 16);        if (!lynx->phyic.reg_1394a && !size) {                hpsb_selfid_received(host, lsid);        }        while (size > 0) {                struct selfid *sid = (struct selfid *)q;                if (!lynx->phyic.reg_1394a && !sid->extended                     && (sid->phy_id == (phyid + 1))) {                        hpsb_selfid_received(host, lsid);                }                if (q[0] == ~q[1]) {                        PRINT(KERN_DEBUG, lynx->id, "SelfID packet 0x%x rcvd",                              q[0]);                        hpsb_selfid_received(host, q[0]);                } else {                        PRINT(KERN_INFO, lynx->id,                              "inconsistent selfid 0x%x/0x%x", q[0], q[1]);                }                q += 2;                size -= 8;        }        if (!lynx->phyic.reg_1394a && isroot && phyid != 0) {                hpsb_selfid_received(host, lsid);        }        hpsb_selfid_complete(host, phyid, isroot);        if (host->in_bus_reset) return; /* in bus reset again */        if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); //FIXME: I do not think, we need this here        reg_set_bits(lynx, LINK_CONTROL,                     LINK_CONTROL_RCV_CMP_VALID | LINK_CONTROL_TX_ASYNC_EN                     | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_CYCTIMEREN);}/* This must be called with the respective queue_lock held. */static void send_next(struct ti_lynx *lynx, int what){        struct ti_pcl pcl;        struct lynx_send_data *d;        struct hpsb_packet *packet;        d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);        if (!list_empty(&d->pcl_queue)) {                PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");                BUG();        }        packet = driver_packet(d->queue.next);        list_del(&packet->driver_list);        list_add_tail(&packet->driver_list, &d->pcl_queue);        d->header_dma = pci_map_single(lynx->dev, packet->header,                                       packet->header_size, PCI_DMA_TODEVICE);        if (packet->data_size) {                d->data_dma = pci_map_single(lynx->dev, packet->data,                                             packet->data_size,                                             PCI_DMA_TODEVICE);        } else {                d->data_dma = 0;        }        pcl.next = PCL_NEXT_INVALID;        pcl.async_error_next = PCL_NEXT_INVALID;        pcl.pcl_status = 0;#ifdef __BIG_ENDIAN        pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size;#else        pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size                 | PCL_BIGENDIAN;#endif        pcl.buffer[0].pointer = d->header_dma;        pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size;        pcl.buffer[1].pointer = d->data_dma;        switch (packet->type) {        case hpsb_async:                pcl.buffer[0].control |= PCL_CMD_XMT;                break;        case hpsb_iso:                pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;                break;        case hpsb_raw:                pcl.buffer[0].control |= PCL_CMD_UNFXMT;                break;        }                        if (!packet->data_be) {                pcl.buffer[1].control |= PCL_BIGENDIAN;        }        put_pcl(lynx, d->pcl, &pcl);        run_pcl(lynx, d->pcl_start, d->channel);}/* called from subsystem core */static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet){        struct ti_lynx *lynx = host->hostdata;        struct lynx_send_data *d;        unsigned long flags;        if (packet->data_size >= 4096) {                PRINT(KERN_ERR, lynx->id, "transmit packet data too big (%Zd)",                      packet->data_size);                return 0;        }        switch (packet->type) {        case hpsb_async:        case hpsb_raw:                d = &lynx->async;                break;        case hpsb_iso:                d = &lynx->iso_send;                break;        default:                PRINT(KERN_ERR, lynx->id, "invalid packet type %d",                      packet->type);                return 0;        }        if (packet->tcode == TCODE_WRITEQ            || packet->tcode == TCODE_READQ_RESPONSE) {                cpu_to_be32s(&packet->header[3]);        }        spin_lock_irqsave(&d->queue_lock, flags);	list_add_tail(&packet->driver_list, &d->queue);	if (list_empty(&d->pcl_queue))                send_next(lynx, packet->type);        spin_unlock_irqrestore(&d->queue_lock, flags);        return 1;}/* called from subsystem core */static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg){        struct ti_lynx *lynx = host->hostdata;        int retval = 0;        struct hpsb_packet *packet;	LIST_HEAD(packet_list);        unsigned long flags;	int phy_reg;        switch (cmd) {        case RESET_BUS:                if (reg_read(lynx, LINK_INT_STATUS) & LINK_INT_PHY_BUSRESET) {                        retval = 0;                        break;                }		switch (arg) {		case SHORT_RESET:			if (lynx->phyic.reg_1394a) {				phy_reg = get_phy_reg(lynx, 5);				if (phy_reg == -1) {					PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");					retval = -1;					break;				}				phy_reg |= 0x40;				PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset) on request");				lynx->selfid_size = -1;				lynx->phy_reg0 = -1;				set_phy_reg(lynx, 5, phy_reg); /* set ISBR */				break;			} else {				PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");				/* fall through to long bus reset */			}		case LONG_RESET:			phy_reg = get_phy_reg(lynx, 1);			if (phy_reg == -1) {				PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");				retval = -1;				break;			}			phy_reg |= 0x40;			PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset) on request");			lynx->selfid_size = -1;			lynx->phy_reg0 = -1;			set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */			break;		case SHORT_RESET_NO_FORCE_ROOT:			if (lynx->phyic.reg_1394a) {				phy_reg = get_phy_reg(lynx, 1);				if (phy_reg == -1) {					PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");					retval = -1;					break;				}				if (phy_reg & 0x80) {					phy_reg &= ~0x80;					set_phy_reg(lynx, 1, phy_reg); /* clear RHB */				}				phy_reg = get_phy_reg(lynx, 5);				if (phy_reg == -1) {					PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");					retval = -1;					break;				}				phy_reg |= 0x40;				PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, no force_root) on request");				lynx->selfid_size = -1;				lynx->phy_reg0 = -1;				set_phy_reg(lynx, 5, phy_reg); /* set ISBR */				break;			} else {				PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");				/* fall through to long bus reset */			}		case LONG_RESET_NO_FORCE_ROOT:			phy_reg = get_phy_reg(lynx, 1);			if (phy_reg == -1) {				PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");				retval = -1;				break;			}			phy_reg &= ~0x80;			phy_reg |= 0x40;			PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, no force_root) on request");			lynx->selfid_size = -1;			lynx->phy_reg0 = -1;			set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */			break;		case SHORT_RESET_FORCE_ROOT:			if (lynx->phyic.reg_1394a) {				phy_reg = get_phy_reg(lynx, 1);				if (phy_reg == -1) {					PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");					retval = -1;					break;				}				if (!(phy_reg & 0x80)) {					phy_reg |= 0x80;					set_phy_reg(lynx, 1, phy_reg); /* set RHB */				}				phy_reg = get_phy_reg(lynx, 5);				if (phy_reg == -1) {					PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");					retval = -1;					break;				}				phy_reg |= 0x40;				PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, force_root set) on request");				lynx->selfid_size = -1;				lynx->phy_reg0 = -1;				set_phy_reg(lynx, 5, phy_reg); /* set ISBR */				break;			} else {				PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");				/* fall through to long bus reset */			}		case LONG_RESET_FORCE_ROOT:			phy_reg = get_phy_reg(lynx, 1);			if (phy_reg == -1) {				PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");				retval = -1;				break;			}			phy_reg |= 0xc0;			PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, force_root set) on request");			lynx->selfid_size = -1;			lynx->phy_reg0 = -1;			set_phy_reg(lynx, 1, phy_reg); /* set IBR and RHB */			break;		default:			PRINT(KERN_ERR, lynx->id, "unknown argument for reset_bus command %d", arg);			retval = -1;		}                break;        case GET_CYCLE_COUNTER:                retval = reg_read(lynx, CYCLE_TIMER);                break;                        case SET_CYCLE_COUNTER:                reg_write(lynx, CYCLE_TIMER, arg);                break;        case SET_BUS_ID:                reg_write(lynx, LINK_ID,                           (arg << 22) | (reg_read(lynx, LINK_ID) & 0x003f0000));                break;                        case ACT_CYCLE_MASTER:                if (arg) {                        reg_set_bits(lynx, LINK_CONTROL,                                     LINK_CONTROL_CYCMASTER);                } else {                        reg_clear_bits(lynx, LINK_CONTROL,                                       LINK_CONTROL_CYCMASTER);                }                break;        case CANCEL_REQUESTS:                spin_lock_irqsave(&lynx->async.queue_lock, flags);                reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0);		list_splice(&lynx->async.queue, &packet_list);		INIT_LIST_HEAD(&lynx->async.queue);                if (list_empty(&lynx->async.pcl_queue)) {                        spin_unlock_irqrestore(&lynx->async.queue_lock, flags);                        PRINTD(KERN_DEBUG, lynx->id, "no async packet in PCL to cancel");                } else {                        struct ti_pcl pcl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -