autopoll.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /***************************************************************************
  2. sys/autopoll.c
  3. -------------------
  4. copyright : (C) 2002 by Frank Mori Hess
  5. email : fmhess@users.sourceforge.net
  6. ***************************************************************************/
  7. /***************************************************************************
  8. * *
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. ***************************************************************************/
  15. #include "ibsys.h"
  16. #include "autopoll.h"
  17. static const unsigned int serial_timeout = 1000000;
  18. unsigned int num_status_bytes( const gpib_status_queue_t *dev )
  19. {
  20. return dev->num_status_bytes;
  21. }
  22. // push status byte onto back of status byte fifo
  23. int push_status_byte( gpib_status_queue_t *device, uint8_t poll_byte )
  24. {
  25. struct list_head *head = &device->status_bytes;
  26. status_byte_t *status;
  27. static const unsigned int max_num_status_bytes = 1024;
  28. int retval;
  29. if( num_status_bytes( device ) >= max_num_status_bytes )
  30. {
  31. uint8_t lost_byte;
  32. device->dropped_byte = 1;
  33. retval = pop_status_byte( device, &lost_byte );
  34. if( retval < 0 ) return retval;
  35. }
  36. status = kmalloc( sizeof( status_byte_t ), GFP_KERNEL );
  37. if( status == NULL ) return -ENOMEM;
  38. INIT_LIST_HEAD( &status->list );
  39. status->poll_byte = poll_byte;
  40. list_add_tail( &status->list, head );
  41. device->num_status_bytes++;
  42. GPIB_DPRINTK( "pushed status byte 0x%x, %i in queue\n",
  43. (int) poll_byte, num_status_bytes( device ) );
  44. return 0;
  45. }
  46. // pop status byte from front of status byte fifo
  47. int pop_status_byte( gpib_status_queue_t *device, uint8_t *poll_byte )
  48. {
  49. struct list_head *head = &device->status_bytes;
  50. struct list_head *front = head->next;
  51. status_byte_t *status;
  52. if( num_status_bytes( device ) == 0 ) return -EIO;
  53. if( front == head ) return -EIO;
  54. if( device->dropped_byte )
  55. {
  56. device->dropped_byte = 0;
  57. return -EPIPE;
  58. }
  59. status = list_entry( front, status_byte_t, list );
  60. *poll_byte = status->poll_byte;
  61. list_del( front );
  62. kfree( status );
  63. device->num_status_bytes--;
  64. GPIB_DPRINTK( "popped status byte 0x%x, %i in queue\n",
  65. (int) *poll_byte, num_status_bytes( device ) );
  66. return 0;
  67. }
  68. gpib_status_queue_t * get_gpib_status_queue( gpib_board_t *board, unsigned int pad, int sad )
  69. {
  70. gpib_status_queue_t *device;
  71. struct list_head *list_ptr;
  72. const struct list_head *head = &board->device_list;
  73. for( list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next )
  74. {
  75. device = list_entry( list_ptr, gpib_status_queue_t, list );
  76. if( gpib_address_equal( device->pad, device->sad, pad, sad ) )
  77. return device;
  78. }
  79. return NULL;
  80. }
  81. int get_serial_poll_byte( gpib_board_t *board, unsigned int pad, int sad, unsigned int usec_timeout,
  82. uint8_t *poll_byte )
  83. {
  84. gpib_status_queue_t *device;
  85. device = get_gpib_status_queue( board, pad, sad );
  86. if( device == NULL ) return -EINVAL;
  87. if( num_status_bytes( device ) )
  88. {
  89. return pop_status_byte( device, poll_byte );
  90. }else
  91. {
  92. return dvrsp( board, pad, sad, usec_timeout, poll_byte );
  93. }
  94. }
  95. int autopoll_all_devices( gpib_board_t *board )
  96. {
  97. int retval;
  98. GPIB_DPRINTK( "entered autopoll_all_devices()\n" );
  99. if( mutex_lock_interruptible( &board->mutex ) )
  100. {
  101. return -ERESTARTSYS;
  102. }
  103. GPIB_DPRINTK( "autopoll has board lock\n" );
  104. retval = serial_poll_all( board, serial_timeout );
  105. if( retval < 0 )
  106. {
  107. mutex_unlock( &board->mutex );
  108. return retval;
  109. }
  110. GPIB_DPRINTK( "autopoll_all_devices() complete\n" );
  111. /* need to wake wait queue in case someone is
  112. * waiting on RQS */
  113. wake_up_interruptible( &board->wait );
  114. mutex_unlock( &board->mutex );
  115. return retval;
  116. }