write.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /***************************************************************************
  2. nec7210/write.c
  3. -------------------
  4. begin : Dec 2001
  5. copyright : (C) 2001, 2002 by Frank Mori Hess
  6. email : fmhess@users.sourceforge.net
  7. ***************************************************************************/
  8. /***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************/
  16. #include "board.h"
  17. #include <linux/string.h>
  18. #include <asm/dma.h>
  19. static int pio_write_wait(gpib_board_t *board, nec7210_private_t *priv,
  20. short wake_on_lacs, short wake_on_atn, short wake_on_bus_error)
  21. {
  22. // wait until byte is ready to be sent
  23. if(wait_event_interruptible(board->wait,
  24. (test_bit(TACS_NUM, &board->status) && test_bit(WRITE_READY_BN, &priv->state)) ||
  25. test_bit(DEV_CLEAR_BN, &priv->state) ||
  26. (wake_on_bus_error && test_bit(BUS_ERROR_BN, &priv->state)) ||
  27. (wake_on_lacs && test_bit(LACS_NUM, &board->status)) ||
  28. (wake_on_atn && test_bit(ATN_NUM, &board->status)) ||
  29. test_bit(TIMO_NUM, &board->status)))
  30. {
  31. GPIB_DPRINTK( "gpib write interrupted\n" );
  32. return -ERESTARTSYS;
  33. }
  34. if(test_bit(TIMO_NUM, &board->status))
  35. {
  36. printk("nec7210: write timed out\n");
  37. return -ETIMEDOUT;
  38. }
  39. if(test_bit(DEV_CLEAR_BN, &priv->state))
  40. {
  41. printk("nec7210: write interrupted by clear\n");
  42. return -EINTR;
  43. }
  44. if(wake_on_bus_error && test_and_clear_bit(BUS_ERROR_BN, &priv->state))
  45. {
  46. GPIB_DPRINTK("nec7210: bus error on write\n");
  47. return -EIO;
  48. }
  49. return 0;
  50. }
  51. static int pio_write(gpib_board_t *board, nec7210_private_t *priv,
  52. uint8_t *buffer, size_t length, size_t *bytes_written)
  53. {
  54. size_t last_count = 0;
  55. ssize_t retval = 0;
  56. unsigned long flags;
  57. const int max_bus_errors = (length > 1000) ? length : 1000;
  58. int bus_error_count = 0;
  59. *bytes_written = 0;
  60. clear_bit(BUS_ERROR_BN, &priv->state);
  61. while(*bytes_written < length)
  62. {
  63. if(need_resched())
  64. schedule();
  65. retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210);
  66. if(retval == -EIO)
  67. {
  68. /* resend last byte on bus error */
  69. *bytes_written = last_count;
  70. GPIB_DPRINTK("resending %c\n", buffer[*bytes_written]);
  71. /* we can get unrecoverable bus errors,
  72. * so give up after a while */
  73. bus_error_count++;
  74. if(bus_error_count > max_bus_errors) return retval;
  75. else continue;
  76. }else if( retval < 0 ) return retval;
  77. spin_lock_irqsave(&board->spinlock, flags);
  78. clear_bit(BUS_ERROR_BN, &priv->state);
  79. clear_bit(WRITE_READY_BN, &priv->state);
  80. last_count = *bytes_written;
  81. write_byte(priv, buffer[(*bytes_written)++], CDOR);
  82. spin_unlock_irqrestore(&board->spinlock, flags);
  83. }
  84. retval = pio_write_wait(board, priv, 1, 1, priv->type == NEC7210);
  85. return retval;
  86. }
  87. #if 0
  88. static ssize_t __dma_write(gpib_board_t *board, nec7210_private_t *priv, dma_addr_t address, size_t length)
  89. {
  90. unsigned long flags, dma_irq_flags;
  91. int residue = 0;
  92. int retval = 0;
  93. spin_lock_irqsave(&board->spinlock, flags);
  94. /* program dma controller */
  95. dma_irq_flags = claim_dma_lock();
  96. disable_dma(priv->dma_channel);
  97. clear_dma_ff(priv->dma_channel);
  98. set_dma_count(priv->dma_channel, length);
  99. set_dma_addr(priv->dma_channel, address);
  100. set_dma_mode(priv->dma_channel, DMA_MODE_WRITE );
  101. enable_dma(priv->dma_channel);
  102. release_dma_lock(dma_irq_flags);
  103. // enable board's dma for output
  104. nec7210_set_reg_bits( priv, IMR2, HR_DMAO, HR_DMAO );
  105. clear_bit(WRITE_READY_BN, &priv->state);
  106. set_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state);
  107. spin_unlock_irqrestore(&board->spinlock, flags);
  108. // suspend until message is sent
  109. if(wait_event_interruptible(board->wait, test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0 ||
  110. test_bit( BUS_ERROR_BN, &priv->state ) || test_bit( DEV_CLEAR_BN, &priv->state ) ||
  111. test_bit(TIMO_NUM, &board->status)))
  112. {
  113. GPIB_DPRINTK( "gpib write interrupted!\n" );
  114. retval = -ERESTARTSYS;
  115. }
  116. if(test_bit(TIMO_NUM, &board->status))
  117. retval = -ETIMEDOUT;
  118. if( test_and_clear_bit( DEV_CLEAR_BN, &priv->state ) )
  119. retval = -EINTR;
  120. if( test_and_clear_bit( BUS_ERROR_BN, &priv->state ) )
  121. retval = -EIO;
  122. // disable board's dma
  123. nec7210_set_reg_bits( priv, IMR2, HR_DMAO, 0 );
  124. dma_irq_flags = claim_dma_lock();
  125. clear_dma_ff(priv->dma_channel);
  126. disable_dma(priv->dma_channel);
  127. residue = get_dma_residue(priv->dma_channel);
  128. release_dma_lock( dma_irq_flags );
  129. if(residue)
  130. retval = -EPIPE;
  131. return retval ? retval : length;
  132. }
  133. static ssize_t dma_write(gpib_board_t *board, nec7210_private_t *priv, uint8_t *buffer, size_t length)
  134. {
  135. size_t remain = length;
  136. size_t transfer_size;
  137. ssize_t retval = 0;
  138. while(remain > 0)
  139. {
  140. transfer_size = (priv->dma_buffer_length < remain) ? priv->dma_buffer_length : remain;
  141. memcpy(priv->dma_buffer, buffer, transfer_size);
  142. retval = __dma_write(board, priv, priv->dma_buffer_addr, transfer_size);
  143. if(retval < 0) break;
  144. remain -= retval;
  145. buffer += retval;
  146. }
  147. if(retval < 0) return retval;
  148. return length - remain;
  149. }
  150. #endif
  151. int nec7210_write(gpib_board_t *board, nec7210_private_t *priv, uint8_t *buffer, size_t length,
  152. int send_eoi, size_t *bytes_written)
  153. {
  154. int retval = 0;
  155. *bytes_written = 0;
  156. clear_bit( DEV_CLEAR_BN, &priv->state ); //XXX
  157. if(send_eoi)
  158. {
  159. length-- ; /* save the last byte for sending EOI */
  160. }
  161. if(length > 0)
  162. {
  163. if(0 /*priv->dma_channel*/)
  164. { // isa dma transfer
  165. /* dma writes are unreliable since they can't recover from bus errors
  166. * (which happen when ATN is asserted in the middle of a write) */
  167. #if 0
  168. retval = dma_write(board, priv, buffer, length);
  169. if(retval < 0)
  170. return retval;
  171. else count += retval;
  172. #endif
  173. }else
  174. { // PIO transfer
  175. size_t num_bytes;
  176. retval = pio_write(board, priv, buffer, length, &num_bytes);
  177. *bytes_written += num_bytes;
  178. if(retval < 0)
  179. {
  180. return retval;
  181. }
  182. }
  183. }
  184. if(send_eoi)
  185. {
  186. size_t num_bytes;
  187. /*send EOI */
  188. write_byte(priv, AUX_SEOI, AUXMR);
  189. retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes);
  190. *bytes_written += num_bytes;
  191. if(retval < 0)
  192. {
  193. return retval;
  194. }
  195. }
  196. return retval;
  197. }
  198. EXPORT_SYMBOL(nec7210_write);