interrupt.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /***************************************************************************
  2. nec7210/interrupt.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 <asm/bitops.h>
  18. #include <asm/dma.h>
  19. static inline short nec7210_atn_has_changed(gpib_board_t *board, nec7210_private_t *priv)
  20. {
  21. short address_status_bits = read_byte(priv, ADSR);
  22. if(address_status_bits & HR_NATN)
  23. {
  24. if(test_bit(ATN_NUM, &board->status))
  25. return 1;
  26. else return 0;
  27. }else
  28. {
  29. if(test_bit(ATN_NUM, &board->status))
  30. return 0;
  31. else return 1;
  32. }
  33. return -1;
  34. }
  35. /*
  36. * interrupt service routine
  37. */
  38. irqreturn_t nec7210_interrupt( gpib_board_t *board, nec7210_private_t *priv )
  39. {
  40. int status1, status2;
  41. // read interrupt status (also clears status)
  42. status1 = read_byte(priv, ISR1);
  43. status2 = read_byte(priv, ISR2);
  44. return nec7210_interrupt_have_status( board, priv, status1, status2 );
  45. }
  46. irqreturn_t nec7210_interrupt_have_status( gpib_board_t *board,
  47. nec7210_private_t *priv, int status1, int status2 )
  48. {
  49. unsigned long dma_flags;
  50. int retval = IRQ_NONE;
  51. // record service request in status
  52. if(status2 & HR_SRQI)
  53. {
  54. set_bit(SRQI_NUM, &board->status);
  55. }
  56. // change in lockout status
  57. if(status2 & HR_LOKC)
  58. {
  59. if(status2 & HR_LOK)
  60. set_bit(LOK_NUM, &board->status);
  61. else
  62. clear_bit(LOK_NUM, &board->status);
  63. }
  64. // change in remote status
  65. if(status2 & HR_REMC)
  66. {
  67. if(status2 & HR_REM)
  68. set_bit(REM_NUM, &board->status);
  69. else
  70. clear_bit(REM_NUM, &board->status);
  71. }
  72. // record reception of END
  73. if(status1 & HR_END)
  74. {
  75. set_bit(RECEIVED_END_BN, &priv->state);
  76. if( ( priv->auxa_bits & HR_HANDSHAKE_MASK ) == HR_HLDE )
  77. set_bit( RFD_HOLDOFF_BN, &priv->state);
  78. }
  79. // get incoming data in PIO mode
  80. if((status1 & HR_DI))
  81. {
  82. set_bit(READ_READY_BN, &priv->state);
  83. if( ( priv->auxa_bits & HR_HANDSHAKE_MASK ) == HR_HLDA )
  84. set_bit( RFD_HOLDOFF_BN, &priv->state);
  85. }
  86. #if 0
  87. // check for dma read transfer complete
  88. if(test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state))
  89. {
  90. dma_flags = claim_dma_lock();
  91. disable_dma(priv->dma_channel);
  92. clear_dma_ff(priv->dma_channel);
  93. if((status1 & HR_END) || get_dma_residue(priv->dma_channel) == 0)
  94. {
  95. clear_bit(DMA_READ_IN_PROGRESS_BN, &priv->state);
  96. }else
  97. enable_dma(priv->dma_channel);
  98. release_dma_lock( dma_flags );
  99. }
  100. #endif
  101. if((status1 & HR_DO))
  102. {
  103. if(test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0)
  104. set_bit(WRITE_READY_BN, &priv->state);
  105. #if 0
  106. if(test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state)) // write data, isa dma mode
  107. {
  108. // check if dma transfer is complete
  109. dma_flags = claim_dma_lock();
  110. disable_dma(priv->dma_channel);
  111. clear_dma_ff(priv->dma_channel);
  112. if(get_dma_residue(priv->dma_channel) == 0)
  113. {
  114. clear_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state);
  115. // XXX race? byte may still be in CDOR reg
  116. }else
  117. {
  118. clear_bit(WRITE_READY_BN, &priv->state);
  119. enable_dma(priv->dma_channel);
  120. }
  121. release_dma_lock( dma_flags );
  122. }
  123. #endif
  124. }
  125. // outgoing command can be sent
  126. if(status2 & HR_CO)
  127. {
  128. set_bit(COMMAND_READY_BN, &priv->state);
  129. }
  130. // command pass through received
  131. if(status1 & HR_CPT)
  132. {
  133. unsigned int command;
  134. command = read_byte(priv, CPTR);
  135. write_byte(priv, AUX_NVAL, AUXMR);
  136. printk( "gpib: command pass through 0x%x\n", command );
  137. }
  138. if(status1 & HR_ERR)
  139. {
  140. set_bit( BUS_ERROR_BN, &priv->state );
  141. printk("nec7210: bus error\n");
  142. }
  143. if( status1 & HR_DEC )
  144. {
  145. unsigned short address_status_bits = read_byte(priv, ADSR);
  146. // ignore device clear events if we are controller in charge
  147. if((address_status_bits & HR_CIC) == 0)
  148. {
  149. push_gpib_event( board, EventDevClr );
  150. set_bit( DEV_CLEAR_BN, &priv->state );
  151. }
  152. }
  153. if( status1 & HR_DET )
  154. {
  155. push_gpib_event( board, EventDevTrg );
  156. }
  157. if((status1 & priv->reg_bits[ IMR1 ]) ||
  158. (status2 & (priv->reg_bits[ IMR2 ] & IMR2_ENABLE_INTR_MASK)) ||
  159. nec7210_atn_has_changed(board, priv))
  160. {
  161. GPIB_DPRINTK( "minor %i, isr1 0x%x, imr1 0x%x, isr2 0x%x, imr2 0x%x\n",
  162. board->minor, status1, priv->reg_bits[ IMR1 ], status2, priv->reg_bits[ IMR2 ] );
  163. update_status_nolock(board, priv);
  164. wake_up_interruptible(&board->wait); /* wake up sleeping process */
  165. retval = IRQ_HANDLED;
  166. }
  167. return retval;
  168. }
  169. EXPORT_SYMBOL(nec7210_interrupt);
  170. EXPORT_SYMBOL(nec7210_interrupt_have_status);