📄 ieee1394_core.c
字号:
}}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 - np"); 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"); 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_task_queue(&packet->complete_tq);}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_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; nodeid_t source = data[1] >> 16; nodeid_t dest = data[0] >> 16; 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); if (!write_acked && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) { /* 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); if (!write_acked && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) { /* not a broadcast write, reply */ PREP_REPLY_PACKET(0); fill_async_write_resp(packet, rcode); send_packet_nocare(packet); } break; case TCODE_READQ: PREP_REPLY_PACKET(0); addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; rcode = highlevel_read(host, source, data, addr, 4); fill_async_readquad_resp(packet, rcode, *data); 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); fill_async_readblock_resp(packet, rcode, length); send_packet_nocare(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); 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); 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); 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); fill_async_lock_resp(packet, rcode, extcode, 8); break; default: fill_async_lock_resp(packet, RCODE_TYPE_ERROR, extcode, 0); } send_packet_nocare(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; }#ifdef CONFIG_IEEE1394_VERBOSEDEBUG dump_packet("received packet:", data, size);#endif tcode = (data[0] >> 4) & 0xf; switch (tcode) { case TCODE_WRITE_RESPONSE: case TCODE_READQ_RESPONSE: case TCODE_READB_RESPONSE: case TCODE_LOCK_RESPONSE: handle_packet_response(host, tcode, data, size); break; case TCODE_WRITEQ: case TCODE_WRITEB: case TCODE_READQ: case TCODE_READB: case TCODE_LOCK_REQUEST: handle_incoming_packet(host, tcode, data, size, write_acked); break; case TCODE_ISO_DATA: highlevel_iso_receive(host, data, size); break; case TCODE_CYCLE_START: /* simply ignore this packet if it is passed on */ break; default: HPSB_NOTICE("received packet with bogus transaction code %d", tcode); break; }}void abort_requests(struct hpsb_host *host){ unsigned long flags; struct hpsb_packet *packet; struct list_head *lh; LIST_HEAD(llist); host->template->devctl(host, CANCEL_REQUESTS, 0); spin_lock_irqsave(&host->pending_pkt_lock, flags); list_splice(&host->pending_packets, &llist); INIT_LIST_HEAD(&host->pending_packets); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); list_for_each(lh, &llist) { packet = list_entry(lh, struct hpsb_packet, list); packet->state = hpsb_complete; packet->ack_code = ACKX_ABORTED; up(&packet->state_change); run_task_queue(&packet->complete_tq); }}void abort_timedouts(struct hpsb_host *host){ unsigned long flags; struct hpsb_packet *packet; unsigned long expire; struct list_head *lh, *next; LIST_HEAD(expiredlist); spin_lock_irqsave(&host->csr.lock, flags); expire = (host->csr.split_timeout_hi * 8000 + (host->csr.split_timeout_lo >> 19)) * HZ / 8000; /* Avoid shortening of timeout due to rounding errors: */ expire++; spin_unlock_irqrestore(&host->csr.lock, flags); spin_lock_irqsave(&host->pending_pkt_lock, flags); for (lh = host->pending_packets.next; lh != &host->pending_packets; lh = next) { packet = list_entry(lh, struct hpsb_packet, list); next = lh->next; if (time_before(packet->sendtime + expire, jiffies)) { list_del(&packet->list); list_add(&packet->list, &expiredlist); } } if (!list_empty(&host->pending_packets)) { queue_task(&host->timeout_tq, &tq_timer); } spin_unlock_irqrestore(&host->pending_pkt_lock, flags); list_for_each(lh, &expiredlist) { packet = list_entry(lh, struct hpsb_packet, list); packet->state = hpsb_complete; packet->ack_code = ACKX_TIMEOUT; up(&packet->state_change); run_task_queue(&packet->complete_tq); }}static int __init ieee1394_init(void){ hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet), 0, 0, NULL, NULL); init_hpsb_highlevel(); init_csr(); if (!disable_nodemgr) init_ieee1394_nodemgr(); else HPSB_INFO("nodemgr functionality disabled"); return 0;}static void __exit ieee1394_cleanup(void){ if (!disable_nodemgr) cleanup_ieee1394_nodemgr(); cleanup_csr(); kmem_cache_destroy(hpsb_packet_cache);}module_init(ieee1394_init);module_exit(ieee1394_cleanup);/* Exported symbols */EXPORT_SYMBOL(hpsb_register_lowlevel);EXPORT_SYMBOL(hpsb_unregister_lowlevel);EXPORT_SYMBOL(hpsb_get_host);EXPORT_SYMBOL(hpsb_inc_host_usage);EXPORT_SYMBOL(hpsb_dec_host_usage);EXPORT_SYMBOL(hpsb_speedto_str);EXPORT_SYMBOL(alloc_hpsb_packet);EXPORT_SYMBOL(free_hpsb_packet);EXPORT_SYMBOL(hpsb_send_packet);EXPORT_SYMBOL(hpsb_reset_bus);EXPORT_SYMBOL(hpsb_bus_reset);EXPORT_SYMBOL(hpsb_selfid_received);EXPORT_SYMBOL(hpsb_selfid_complete);EXPORT_SYMBOL(hpsb_packet_sent);EXPORT_SYMBOL(hpsb_packet_received);EXPORT_SYMBOL(get_tlabel);EXPORT_SYMBOL(free_tlabel);EXPORT_SYMBOL(fill_async_readquad);EXPORT_SYMBOL(fill_async_readquad_resp);EXPORT_SYMBOL(fill_async_readblock);EXPORT_SYMBOL(fill_async_readblock_resp);EXPORT_SYMBOL(fill_async_writequad);EXPORT_SYMBOL(fill_async_writeblock);EXPORT_SYMBOL(fill_async_write_resp);EXPORT_SYMBOL(fill_async_lock);EXPORT_SYMBOL(fill_async_lock_resp);EXPORT_SYMBOL(fill_iso_packet);EXPORT_SYMBOL(fill_phy_packet);EXPORT_SYMBOL(hpsb_make_readqpacket);EXPORT_SYMBOL(hpsb_make_readbpacket);EXPORT_SYMBOL(hpsb_make_writeqpacket);EXPORT_SYMBOL(hpsb_make_writebpacket);EXPORT_SYMBOL(hpsb_make_lockpacket);EXPORT_SYMBOL(hpsb_make_phypacket);EXPORT_SYMBOL(hpsb_packet_success);EXPORT_SYMBOL(hpsb_make_packet);EXPORT_SYMBOL(hpsb_read);EXPORT_SYMBOL(hpsb_write);EXPORT_SYMBOL(hpsb_lock);EXPORT_SYMBOL(hpsb_register_highlevel);EXPORT_SYMBOL(hpsb_unregister_highlevel);EXPORT_SYMBOL(hpsb_register_addrspace);EXPORT_SYMBOL(hpsb_listen_channel);EXPORT_SYMBOL(hpsb_unlisten_channel);EXPORT_SYMBOL(highlevel_read);EXPORT_SYMBOL(highlevel_write);EXPORT_SYMBOL(highlevel_lock);EXPORT_SYMBOL(highlevel_lock64);EXPORT_SYMBOL(highlevel_add_host);EXPORT_SYMBOL(highlevel_remove_host);EXPORT_SYMBOL(highlevel_host_reset);EXPORT_SYMBOL(highlevel_add_one_host);EXPORT_SYMBOL(hpsb_guid_get_entry);EXPORT_SYMBOL(hpsb_nodeid_get_entry);EXPORT_SYMBOL(hpsb_get_host_by_ne);EXPORT_SYMBOL(hpsb_guid_fill_packet);EXPORT_SYMBOL(hpsb_register_protocol);EXPORT_SYMBOL(hpsb_unregister_protocol);EXPORT_SYMBOL(hpsb_release_unit_directory);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -