ieee1394_transactions.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:17k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * IEEE 1394 for Linux
  3.  *
  4.  * Transaction support.
  5.  *
  6.  * Copyright (C) 1999 Andreas E. Bombe
  7.  *
  8.  * This code is licensed under the GPL.  See the file COPYING in the root
  9.  * directory of the kernel sources for details.
  10.  */
  11. #include <linux/sched.h>
  12. #include <asm/errno.h>
  13. #include <asm/bitops.h>
  14. #include "ieee1394.h"
  15. #include "ieee1394_types.h"
  16. #include "hosts.h"
  17. #include "ieee1394_core.h"
  18. #include "highlevel.h"
  19. #define PREP_ASYNC_HEAD_ADDRESS(tc) 
  20.         packet->tcode = tc; 
  21.         packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) 
  22.                 | (1 << 8) | (tc << 4); 
  23.         packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); 
  24.         packet->header[2] = addr & 0xffffffff
  25. #define PREP_ASYNC_HEAD_RCODE(tc) 
  26.         packet->tcode = tc; 
  27.         packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) 
  28.                 | (1 << 8) | (tc << 4); 
  29.         packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); 
  30.         packet->header[2] = 0
  31. void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
  32. {
  33.         PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
  34.         packet->header_size = 12;
  35.         packet->data_size = 0;
  36.         packet->expect_response = 1;
  37. }
  38. void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, 
  39.                               quadlet_t data)
  40. {
  41.         PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
  42.         packet->header[3] = data;
  43.         packet->header_size = 16;
  44.         packet->data_size = 0;
  45. }
  46. void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length)
  47. {
  48.         PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
  49.         packet->header[3] = length << 16;
  50.         packet->header_size = 16;
  51.         packet->data_size = 0;
  52.         packet->expect_response = 1;
  53. }
  54. void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, 
  55.                                int length)
  56. {
  57.         if (rcode != RCODE_COMPLETE) {
  58.                 length = 0;
  59.         }
  60.         PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE);
  61.         packet->header[3] = length << 16;
  62.         packet->header_size = 16;
  63.         packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
  64. }
  65. void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data)
  66. {
  67.         PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
  68.         packet->header[3] = data;
  69.         packet->header_size = 16;
  70.         packet->data_size = 0;
  71.         packet->expect_response = 1;
  72. }
  73. void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length)
  74. {
  75.         PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
  76.         packet->header[3] = length << 16;
  77.         packet->header_size = 16;
  78.         packet->expect_response = 1;
  79.         packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
  80. }
  81. void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
  82. {
  83.         PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);
  84.         packet->header[2] = 0;
  85.         packet->header_size = 12;
  86.         packet->data_size = 0;
  87. }
  88. void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, 
  89.                      int length)
  90. {
  91.         PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
  92.         packet->header[3] = (length << 16) | extcode;
  93.         packet->header_size = 16;
  94.         packet->data_size = length;
  95.         packet->expect_response = 1;
  96. }
  97. void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, 
  98.                           int length)
  99. {
  100.         if (rcode != RCODE_COMPLETE) {
  101.                 length = 0;
  102.         }
  103.         PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE);
  104.         packet->header[3] = (length << 16) | extcode;
  105.         packet->header_size = 16;
  106.         packet->data_size = length;
  107. }
  108. void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
  109.                      int tag, int sync)
  110. {
  111.         packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
  112.                 | (TCODE_ISO_DATA << 4) | sync;
  113.         packet->header_size = 4;
  114.         packet->data_size = length;
  115.         packet->type = hpsb_iso;
  116.         packet->tcode = TCODE_ISO_DATA;
  117. }
  118. void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data) 
  119.         packet->header[0] = data;
  120.         packet->header[1] = ~data; 
  121.         packet->header_size = 8;
  122.         packet->data_size = 0;
  123.         packet->expect_response = 0;
  124.         packet->type = hpsb_raw;             /* No CRC added */
  125.         packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
  126. }
  127. /**
  128.  * get_tlabel - allocate a transaction label
  129.  * @host: host to be used for transmission
  130.  * @nodeid: the node ID of the transmission target
  131.  * @wait: whether to sleep if no tlabel is available
  132.  *
  133.  * Every asynchronous transaction on the 1394 bus needs a transaction label to
  134.  * match the response to the request.  This label has to be different from any
  135.  * other transaction label in an outstanding request to the same node to make
  136.  * matching possible without ambiguity.
  137.  *
  138.  * There are 64 different tlabels, so an allocated tlabel has to be freed with
  139.  * free_tlabel() after the transaction is complete (unless it's reused again for
  140.  * the same target node).
  141.  *
  142.  * @wait must not be set to true if you are calling from interrupt context.
  143.  *
  144.  * Return value: The allocated transaction label or -1 if there was no free
  145.  * tlabel and @wait is false.
  146.  */
  147. int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait)
  148. {
  149. int tlabel;
  150. unsigned long flags;
  151. if (wait) {
  152. down(&host->tlabel_count);
  153. } else {
  154. if (down_trylock(&host->tlabel_count)) return -1;
  155. }
  156. spin_lock_irqsave(&host->tlabel_lock, flags);
  157. if (host->tlabel_pool[0] != ~0) {
  158. tlabel = ffz(host->tlabel_pool[0]);
  159. host->tlabel_pool[0] |= 1 << tlabel;
  160. } else {
  161. tlabel = ffz(host->tlabel_pool[1]);
  162. host->tlabel_pool[1] |= 1 << tlabel;
  163. tlabel += 32;
  164. }
  165. spin_unlock_irqrestore(&host->tlabel_lock, flags);
  166. return tlabel;
  167. }
  168. /**
  169.  * free_tlabel - free an allocated transaction label
  170.  * @host: host to be used for transmission
  171.  * @nodeid: the node ID of the transmission target
  172.  * @tlabel: the transaction label to free
  173.  *
  174.  * Frees the transaction label allocated with get_tlabel().  The tlabel has to
  175.  * be freed after the transaction is complete (i.e. response was received for a
  176.  * split transaction or packet was sent for a unified transaction).
  177.  *
  178.  * A tlabel must not be freed twice.
  179.  */
  180. void free_tlabel(struct hpsb_host *host, nodeid_t nodeid, int tlabel)
  181. {
  182.         unsigned long flags;
  183.         spin_lock_irqsave(&host->tlabel_lock, flags);
  184.         if (tlabel < 32) {
  185.                 host->tlabel_pool[0] &= ~(1 << tlabel);
  186.         } else {
  187.                 host->tlabel_pool[1] &= ~(1 << (tlabel-32));
  188.         }
  189.         spin_unlock_irqrestore(&host->tlabel_lock, flags);
  190.         up(&host->tlabel_count);
  191. }
  192. int hpsb_packet_success(struct hpsb_packet *packet)
  193. {
  194.         switch (packet->ack_code) {
  195.         case ACK_PENDING:
  196.                 switch ((packet->header[1] >> 12) & 0xf) {
  197.                 case RCODE_COMPLETE:
  198.                         return 0;
  199.                 case RCODE_CONFLICT_ERROR:
  200.                         return -EAGAIN;
  201.                 case RCODE_DATA_ERROR:
  202.                         return -EREMOTEIO;
  203.                 case RCODE_TYPE_ERROR:
  204.                         return -EACCES;
  205.                 case RCODE_ADDRESS_ERROR:
  206.                         return -EINVAL;
  207.                 default:
  208.                         HPSB_ERR("received reserved rcode %d from node %d",
  209.                                  (packet->header[1] >> 12) & 0xf, 
  210.                                  packet->node_id);
  211.                         return -EAGAIN;
  212.                 }
  213.                 HPSB_PANIC("reached unreachable code 1 in " __FUNCTION__);
  214.         case ACK_BUSY_X:
  215.         case ACK_BUSY_A:
  216.         case ACK_BUSY_B:
  217.                 return -EBUSY;
  218.         case ACK_TYPE_ERROR:
  219.                 return -EACCES;
  220.         case ACK_COMPLETE:
  221.                 if (packet->tcode == TCODE_WRITEQ
  222.                     || packet->tcode == TCODE_WRITEB) {
  223.                         return 0;
  224.                 } else {
  225.                         HPSB_ERR("impossible ack_complete from node %d "
  226.                                  "(tcode %d)", packet->node_id, packet->tcode);
  227.                         return -EAGAIN;
  228.                 }
  229.         case ACK_DATA_ERROR:
  230.                 if (packet->tcode == TCODE_WRITEB
  231.                     || packet->tcode == TCODE_LOCK_REQUEST) {
  232.                         return -EAGAIN;
  233.                 } else {
  234.                         HPSB_ERR("impossible ack_data_error from node %d "
  235.                                  "(tcode %d)", packet->node_id, packet->tcode);
  236.                         return -EAGAIN;
  237.                 }
  238.         case ACKX_NONE:
  239.         case ACKX_SEND_ERROR:
  240.         case ACKX_ABORTED:
  241.         case ACKX_TIMEOUT:
  242.                 /* error while sending */
  243.                 return -EAGAIN;
  244.         default:
  245.                 HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
  246.                          packet->ack_code, packet->node_id, packet->tcode);
  247.                 return -EAGAIN;
  248.         }
  249.         HPSB_PANIC("reached unreachable code 2 in " __FUNCTION__);
  250. }
  251. int hpsb_read_trylocal(struct hpsb_host *host, nodeid_t node, u64 addr, 
  252.                        quadlet_t *buffer, size_t length)
  253. {
  254.         if (host->node_id != node) return -1;
  255.         return highlevel_read(host, node, buffer, addr, length);
  256. }
  257. struct hpsb_packet *hpsb_make_readqpacket(struct hpsb_host *host, nodeid_t node,
  258.                                           u64 addr)
  259. {
  260.         struct hpsb_packet *p;
  261.         p = alloc_hpsb_packet(0);
  262.         if (!p) return NULL;
  263.         p->host = host;
  264.         p->tlabel = get_tlabel(host, node, 1);
  265.         p->node_id = node;
  266.         fill_async_readquad(p, addr);
  267.         return p;
  268. }
  269. struct hpsb_packet *hpsb_make_readbpacket(struct hpsb_host *host, nodeid_t node,
  270.                                           u64 addr, size_t length)
  271. {
  272.         struct hpsb_packet *p;
  273.         p = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
  274.         if (!p) return NULL;
  275.         p->host = host;
  276.         p->tlabel = get_tlabel(host, node, 1);
  277.         p->node_id = node;
  278.         fill_async_readblock(p, addr, length);
  279.         return p;
  280. }
  281. struct hpsb_packet *hpsb_make_writeqpacket(struct hpsb_host *host,
  282.                                            nodeid_t node, u64 addr,
  283.                                            quadlet_t data)
  284. {
  285.         struct hpsb_packet *p;
  286.         p = alloc_hpsb_packet(0);
  287.         if (!p) return NULL;
  288.         p->host = host;
  289.         p->tlabel = get_tlabel(host, node, 1);
  290.         p->node_id = node;
  291.         fill_async_writequad(p, addr, data);
  292.         return p;
  293. }
  294. struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host,
  295.                                            nodeid_t node, u64 addr,
  296.                                            size_t length)
  297. {
  298.         struct hpsb_packet *p;
  299.         p = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
  300.         if (!p) return NULL;
  301.         if (length % 4) {
  302.                 p->data[length / 4] = 0;
  303.         }
  304.         p->host = host;
  305.         p->tlabel = get_tlabel(host, node, 1);
  306.         p->node_id = node;
  307.         fill_async_writeblock(p, addr, length);
  308.         return p;
  309. }
  310. struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
  311.                                          u64 addr, int extcode)
  312. {
  313.         struct hpsb_packet *p;
  314.         p = alloc_hpsb_packet(8);
  315.         if (!p) return NULL;
  316.         p->host = host;
  317.         p->tlabel = get_tlabel(host, node, 1);
  318.         p->node_id = node;
  319.         switch (extcode) {
  320.         case EXTCODE_FETCH_ADD:
  321.         case EXTCODE_LITTLE_ADD:
  322.                 fill_async_lock(p, addr, extcode, 4);
  323.                 break;
  324.         default:
  325.                 fill_async_lock(p, addr, extcode, 8);
  326.                 break;
  327.         }
  328.         return p;
  329. }
  330. struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
  331.                                         quadlet_t data) 
  332. {
  333.         struct hpsb_packet *p; 
  334.         p = alloc_hpsb_packet(0); 
  335.         if (!p) return NULL; 
  336.         p->host = host; 
  337.         fill_phy_packet(p, data); 
  338.         return p; 
  339. }
  340. /*
  341.  * FIXME - these functions should probably read from / write to user space to
  342.  * avoid in kernel buffers for user space callers
  343.  */
  344. int hpsb_read(struct hpsb_host *host, nodeid_t node, u64 addr,
  345.               quadlet_t *buffer, size_t length)
  346. {
  347.         struct hpsb_packet *packet;
  348.         int retval = 0;
  349.         
  350.         if (length == 0) {
  351.                 return -EINVAL;
  352.         }
  353.         if (host->node_id == node) {
  354.                 switch(highlevel_read(host, node, buffer, addr, length)) {
  355.                 case RCODE_COMPLETE:
  356.                         return 0;
  357.                 case RCODE_TYPE_ERROR:
  358.                         return -EACCES;
  359.                 case RCODE_ADDRESS_ERROR:
  360.                 default:
  361.                         return -EINVAL;
  362.                 }
  363.         }
  364.         if (length == 4) {
  365.                 packet = hpsb_make_readqpacket(host, node, addr);
  366.         } else {
  367.                 packet = hpsb_make_readbpacket(host, node, addr, length);
  368.         }
  369.         if (!packet) {
  370.                 return -ENOMEM;
  371.         }
  372. packet->generation = get_hpsb_generation(host);
  373.         if (!hpsb_send_packet(packet)) {
  374. retval = -EINVAL;
  375. goto hpsb_read_fail;
  376. }
  377.         down(&packet->state_change);
  378.         down(&packet->state_change);
  379.         retval = hpsb_packet_success(packet);
  380.         if (retval == 0) {
  381.                 if (length == 4) {
  382.                         *buffer = packet->header[3];
  383.                 } else {
  384.                         memcpy(buffer, packet->data, length);
  385.                 }
  386.         }
  387. hpsb_read_fail:
  388.         free_tlabel(host, node, packet->tlabel);
  389.         free_hpsb_packet(packet);
  390.         return retval;
  391. }
  392. struct hpsb_packet *hpsb_make_packet (struct hpsb_host *host, nodeid_t node,
  393.       u64 addr, quadlet_t *buffer, size_t length)
  394. {
  395.         struct hpsb_packet *packet;
  396.         
  397.         if (length == 0)
  398.                 return NULL;
  399.         if (length == 4)
  400.                 packet = hpsb_make_writeqpacket(host, node, addr, *buffer);
  401.         else
  402.                 packet = hpsb_make_writebpacket(host, node, addr, length);
  403.         if (!packet)
  404.                 return NULL;
  405. /* Sometimes this may be called without data, just to allocate the
  406.  * packet. */
  407.         if (length != 4 && buffer)
  408.                 memcpy(packet->data, buffer, length);
  409. return packet;
  410. }
  411. int hpsb_write(struct hpsb_host *host, nodeid_t node, u64 addr,
  412.        quadlet_t *buffer, size_t length)
  413. {
  414. struct hpsb_packet *packet;
  415. int retval;
  416. if (length == 0)
  417. return -EINVAL;
  418. if (host->node_id == node) {
  419. switch(highlevel_write(host, node, node, buffer, addr, length)) {
  420. case RCODE_COMPLETE:
  421. return 0;
  422. case RCODE_TYPE_ERROR:
  423. return -EACCES;
  424. case RCODE_ADDRESS_ERROR:
  425. default:
  426. return -EINVAL;
  427. }
  428. }
  429. packet = hpsb_make_packet (host, node, addr, buffer, length);
  430. if (!packet)
  431. return -ENOMEM;
  432. packet->generation = get_hpsb_generation(host);
  433.         if (!hpsb_send_packet(packet)) {
  434. retval = -EINVAL;
  435. goto hpsb_write_fail;
  436. }
  437.         down(&packet->state_change);
  438.         down(&packet->state_change);
  439.         retval = hpsb_packet_success(packet);
  440. hpsb_write_fail:
  441.         free_tlabel(host, node, packet->tlabel);
  442.         free_hpsb_packet(packet);
  443.         return retval;
  444. }
  445. /* We need a hpsb_lock64 function for the 64 bit equivalent.  Probably. */
  446. int hpsb_lock(struct hpsb_host *host, nodeid_t node, u64 addr, int extcode,
  447.               quadlet_t *data, quadlet_t arg)
  448. {
  449.         struct hpsb_packet *packet;
  450.         int retval = 0, length;
  451.         
  452.         if (host->node_id == node) {
  453.                 switch(highlevel_lock(host, node, data, addr, *data, arg,
  454.                                       extcode)) {
  455.                 case RCODE_COMPLETE:
  456.                         return 0;
  457.                 case RCODE_TYPE_ERROR:
  458.                         return -EACCES;
  459.                 case RCODE_ADDRESS_ERROR:
  460.                 default:
  461.                         return -EINVAL;
  462.                 }
  463.         }
  464.         packet = alloc_hpsb_packet(8);
  465.         if (!packet) {
  466.                 return -ENOMEM;
  467.         }
  468.         packet->host = host;
  469.         packet->tlabel = get_tlabel(host, node, 1);
  470.         packet->node_id = node;
  471.         switch (extcode) {
  472.         case EXTCODE_MASK_SWAP:
  473.         case EXTCODE_COMPARE_SWAP:
  474.         case EXTCODE_BOUNDED_ADD:
  475.         case EXTCODE_WRAP_ADD:
  476.                 length = 8;
  477.                 packet->data[0] = arg;
  478.                 packet->data[1] = *data;
  479.                 break;
  480.         case EXTCODE_FETCH_ADD:
  481.         case EXTCODE_LITTLE_ADD:
  482.                 length = 4;
  483.                 packet->data[0] = *data;
  484.                 break;
  485.         default:
  486.                 return -EINVAL;
  487.         }
  488.         fill_async_lock(packet, addr, extcode, length);
  489. packet->generation = get_hpsb_generation(host);
  490.         if (!hpsb_send_packet(packet)) {
  491. retval = -EINVAL;
  492. goto hpsb_lock_fail;
  493. }
  494.         down(&packet->state_change);
  495.         down(&packet->state_change);
  496.         retval = hpsb_packet_success(packet);
  497.         if (retval == 0) {
  498.                 *data = packet->data[0];
  499.         }
  500. hpsb_lock_fail:
  501.         free_tlabel(host, node, packet->tlabel);
  502.         free_hpsb_packet(packet);
  503.         return retval;
  504. }