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

📄 ieee1394_core.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Return value: 0 for success or error number otherwise. */int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt){	struct hpsb_packet *packet;	int retval = 0;	if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||	   (rootid == -1 && gapcnt == -1)) {		HPSB_DEBUG("Invalid Parameter: rootid = %d   gapcnt = %d",			   rootid, gapcnt);		return -EINVAL;	}	packet = alloc_hpsb_packet(0);	if (!packet)		return -ENOMEM;	packet->host = host;	packet->header_size = 8;	packet->data_size = 0;	packet->expect_response = 0;	packet->no_waiter = 0;	packet->type = hpsb_raw;	packet->header[0] = 0;	if (rootid != -1)		packet->header[0] |= rootid << 24 | 1 << 23;	if (gapcnt != -1)		packet->header[0] |= gapcnt << 16 | 1 << 22;	packet->header[1] = ~packet->header[0];	packet->generation = get_hpsb_generation(host);	if (!hpsb_send_packet(packet)) {		retval = -EINVAL;		goto fail;	}	down(&packet->state_change);	down(&packet->state_change);fail:	free_hpsb_packet(packet);	return retval;}/** * hpsb_send_packet - transmit a packet on the bus * @packet: packet to send * * The packet is sent through the host specified in the packet->host field. * Before sending, the packet's transmit speed is automatically determined using * the local speed map when it is an async, non-broadcast packet. * * Possibilities for failure are that host is either not initialized, in bus * reset, the packet's generation number doesn't match the current generation * number or the host reports a transmit error. * * Return value: False (0) on failure, true (1) otherwise. */int hpsb_send_packet(struct hpsb_packet *packet){        struct hpsb_host *host = packet->host;        if (host->is_shutdown || host->in_bus_reset            || (packet->generation != get_hpsb_generation(host))) {                return 0;        }        packet->state = hpsb_queued;        if (packet->node_id == host->node_id)        { /* it is a local request, so handle it locally */                quadlet_t *data;                size_t size=packet->data_size+packet->header_size;                data = kmalloc(packet->header_size + packet->data_size, GFP_ATOMIC);                if (!data) {                        HPSB_ERR("unable to allocate memory for concatenating header and data");                        return 0;                }                memcpy(data, packet->header, packet->header_size);                if (packet->data_size)                {                        if (packet->data_be) {                                memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size);                        } else {                                int i;                                quadlet_t *my_data=(quadlet_t*) ((u8*) data + packet->data_size);                                for (i=0; i < packet->data_size/4; i++) {                                        my_data[i] = cpu_to_be32(packet->data[i]);                                }                        }                }                dump_packet("send packet local:", packet->header,                            packet->header_size);                hpsb_packet_sent(host, packet,  packet->expect_response?ACK_PENDING:ACK_COMPLETE);                hpsb_packet_received(host, data, size, 0);                kfree(data);                return 1;        }        if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {                packet->speed_code =                        host->speed_map[NODEID_TO_NODE(host->node_id) * 64                                       + NODEID_TO_NODE(packet->node_id)];        }        switch (packet->speed_code) {        case 2:                dump_packet("send packet 400:", packet->header,                            packet->header_size);                break;        case 1:                dump_packet("send packet 200:", packet->header,                            packet->header_size);                break;        default:                dump_packet("send packet 100:", packet->header,                            packet->header_size);        }        return host->driver->transmit_packet(host, packet);}static void send_packet_nocare(struct hpsb_packet *packet){        if (!hpsb_send_packet(packet)) {                free_hpsb_packet(packet);        }}void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,                            size_t size){        struct hpsb_packet *packet = NULL;        struct list_head *lh;        int tcode_match = 0;        int tlabel;        unsigned long flags;        tlabel = (data[0] >> 10) & 0x3f;        spin_lock_irqsave(&host->pending_pkt_lock, flags);        list_for_each(lh, &host->pending_packets) {                packet = list_entry(lh, struct hpsb_packet, list);                if ((packet->tlabel == tlabel)                    && (packet->node_id == (data[1] >> 16))){                        break;                }        }        if (lh == &host->pending_packets) {                HPSB_DEBUG("unsolicited response packet received - no tlabel match");                dump_packet("contents:", data, 16);                spin_unlock_irqrestore(&host->pending_pkt_lock, flags);                return;        }        switch (packet->tcode) {        case TCODE_WRITEQ:        case TCODE_WRITEB:                if (tcode == TCODE_WRITE_RESPONSE) tcode_match = 1;                break;        case TCODE_READQ:                if (tcode == TCODE_READQ_RESPONSE) tcode_match = 1;                break;        case TCODE_READB:                if (tcode == TCODE_READB_RESPONSE) tcode_match = 1;                break;        case TCODE_LOCK_REQUEST:                if (tcode == TCODE_LOCK_RESPONSE) tcode_match = 1;                break;        }        if (!tcode_match || (packet->tlabel != tlabel)            || (packet->node_id != (data[1] >> 16))) {                HPSB_INFO("unsolicited response packet received - tcode mismatch");                dump_packet("contents:", data, 16);                spin_unlock_irqrestore(&host->pending_pkt_lock, flags);                return;        }        list_del(&packet->list);        spin_unlock_irqrestore(&host->pending_pkt_lock, flags);        /* FIXME - update size fields? */        switch (tcode) {        case TCODE_WRITE_RESPONSE:                memcpy(packet->header, data, 12);                break;        case TCODE_READQ_RESPONSE:                memcpy(packet->header, data, 16);                break;        case TCODE_READB_RESPONSE:                memcpy(packet->header, data, 16);                memcpy(packet->data, data + 4, size - 16);                break;        case TCODE_LOCK_RESPONSE:                memcpy(packet->header, data, 16);                memcpy(packet->data, data + 4, (size - 16) > 8 ? 8 : size - 16);                break;        }        packet->state = hpsb_complete;        up(&packet->state_change);	run_packet_complete(packet);}static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,					       quadlet_t *data, size_t dsize){        struct hpsb_packet *p;        dsize += (dsize % 4 ? 4 - (dsize % 4) : 0);        p = alloc_hpsb_packet(dsize);        if (p == NULL) {                /* FIXME - send data_error response */                return NULL;        }        p->type = hpsb_async;        p->state = hpsb_unused;        p->host = host;        p->node_id = data[1] >> 16;        p->tlabel = (data[0] >> 10) & 0x3f;        p->no_waiter = 1;	p->generation = get_hpsb_generation(host);        if (dsize % 4) {                p->data[dsize / 4] = 0;        }        return p;}#define PREP_ASYNC_HEAD_RCODE(tc) \	packet->tcode = tc; \	packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \		| (1 << 8) | (tc << 4); \	packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \	packet->header[2] = 0static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,                              quadlet_t data){	PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);	packet->header[3] = data;	packet->header_size = 16;	packet->data_size = 0;}static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,                               int length){	if (rcode != RCODE_COMPLETE)		length = 0;	PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE);	packet->header[3] = length << 16;	packet->header_size = 16;	packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);}static void fill_async_write_resp(struct hpsb_packet *packet, int rcode){	PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);	packet->header[2] = 0;	packet->header_size = 12;	packet->data_size = 0;}static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,                          int length){	if (rcode != RCODE_COMPLETE)		length = 0;	PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE);	packet->header[3] = (length << 16) | extcode;	packet->header_size = 16;	packet->data_size = length;}#define PREP_REPLY_PACKET(length) \                packet = create_reply_packet(host, data, length); \                if (packet == NULL) breakstatic void handle_incoming_packet(struct hpsb_host *host, int tcode,				   quadlet_t *data, size_t size, int write_acked){        struct hpsb_packet *packet;        int length, rcode, extcode;        quadlet_t buffer;        nodeid_t source = data[1] >> 16;        nodeid_t dest = data[0] >> 16;        u16 flags = (u16) data[0];        u64 addr;        /* big FIXME - no error checking is done for an out of bounds length */        switch (tcode) {        case TCODE_WRITEQ:                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];                rcode = highlevel_write(host, source, dest, data+3,					addr, 4, flags);                if (!write_acked                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)                    && (rcode >= 0)) {                        /* not a broadcast write, reply */                        PREP_REPLY_PACKET(0);                        fill_async_write_resp(packet, rcode);                        send_packet_nocare(packet);                }                break;        case TCODE_WRITEB:                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];                rcode = highlevel_write(host, source, dest, data+4,					addr, data[3]>>16, flags);                if (!write_acked                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)                    && (rcode >= 0)) {                        /* not a broadcast write, reply */                        PREP_REPLY_PACKET(0);                        fill_async_write_resp(packet, rcode);                        send_packet_nocare(packet);                }                break;        case TCODE_READQ:                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];                rcode = highlevel_read(host, source, &buffer, addr, 4, flags);                if (rcode >= 0) {                        PREP_REPLY_PACKET(0);                        fill_async_readquad_resp(packet, rcode, buffer);                        send_packet_nocare(packet);                }                break;        case TCODE_READB:                length = data[3] >> 16;                PREP_REPLY_PACKET(length);                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];                rcode = highlevel_read(host, source, packet->data, addr,                                       length, flags);                if (rcode >= 0) {                        fill_async_readblock_resp(packet, rcode, length);                        send_packet_nocare(packet);                } else {                        free_hpsb_packet(packet);                }                break;        case TCODE_LOCK_REQUEST:                length = data[3] >> 16;                extcode = data[3] & 0xffff;                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];                PREP_REPLY_PACKET(8);                if ((extcode == 0) || (extcode >= 7)) {                        /* let switch default handle error */                        length = 0;                }                switch (length) {                case 4:                        rcode = highlevel_lock(host, source, packet->data, addr,                                               data[4], 0, extcode,flags);                        fill_async_lock_resp(packet, rcode, extcode, 4);                        break;                case 8:                        if ((extcode != EXTCODE_FETCH_ADD)                             && (extcode != EXTCODE_LITTLE_ADD)) {                                rcode = highlevel_lock(host, source,                                                       packet->data, addr,                                                       data[5], data[4],                                                        extcode, flags);                                fill_async_lock_resp(packet, rcode, extcode, 4);                        } else {                                rcode = highlevel_lock64(host, source,                                             (octlet_t *)packet->data, addr,                                             *(octlet_t *)(data + 4), 0ULL,                                             extcode, flags);                                fill_async_lock_resp(packet, rcode, extcode, 8);                        }                        break;                case 16:                        rcode = highlevel_lock64(host, source,                                                 (octlet_t *)packet->data, addr,                                                 *(octlet_t *)(data + 6),                                                 *(octlet_t *)(data + 4),                                                  extcode, flags);                        fill_async_lock_resp(packet, rcode, extcode, 8);                        break;                default:                        rcode = RCODE_TYPE_ERROR;                        fill_async_lock_resp(packet, rcode,                                             extcode, 0);                }                if (rcode >= 0) {                        send_packet_nocare(packet);                } else {                        free_hpsb_packet(packet);                }                break;        }}#undef PREP_REPLY_PACKETvoid hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,                          int write_acked){        int tcode;        if (host->in_bus_reset) {                HPSB_INFO("received packet during reset; ignoring");                return;        }        dump_packet("received packet:", data, size);        tcode = (data[0] >> 4) & 0xf;        switch (tcode) {        case TCODE_WRITE_RESPONSE:        case TCODE_READQ_RESPONSE:        case TCODE_READB_RESPONSE:

⌨️ 快捷键说明

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