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

嵌入式Linux

开发平台:

Unix_Linux

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/sched.h>
  4. #include <linux/signal.h>
  5. #include <linux/errno.h>
  6. #include <linux/init.h>
  7. #include <linux/slab.h>
  8. #include <linux/spinlock.h>
  9. #include <linux/smp_lock.h>
  10. #include <linux/usb.h>
  11. #include <asm/atomic.h>
  12. #include <linux/blk.h>
  13. #include "../scsi/scsi.h"
  14. #include "../scsi/hosts.h"
  15. #include "../scsi/sd.h"
  16. #include "hpusbscsi.h"
  17. #define DEBUG(x...) 
  18. printk( KERN_DEBUG x )
  19. static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
  20. #define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %dn", states[hpusbscsi->state], __LINE__)
  21. /* global variables */
  22. struct list_head hpusbscsi_devices;
  23. //LIST_HEAD(hpusbscsi_devices);
  24. /* USB related parts */
  25. static void *
  26. hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
  27.      const struct usb_device_id *id)
  28. {
  29. struct hpusbscsi *new;
  30. struct usb_interface_descriptor *altsetting =
  31. &(dev->actconfig->interface[interface].altsetting[0]);
  32. int i, result;
  33. /* basic check */
  34. if (altsetting->bNumEndpoints != 3) {
  35. printk (KERN_ERR "Wrong number of endpointsn");
  36. return NULL;
  37. }
  38. /* descriptor allocation */
  39. new =
  40. (struct hpusbscsi *) kmalloc (sizeof (struct hpusbscsi),
  41.       GFP_KERNEL);
  42. if (new == NULL)
  43. return NULL;
  44. DEBUG ("Allocated memoryn");
  45. memset (new, 0, sizeof (struct hpusbscsi));
  46. spin_lock_init (&new->dataurb.lock);
  47. spin_lock_init (&new->controlurb.lock);
  48. new->dev = dev;
  49. init_waitqueue_head (&new->pending);
  50. init_waitqueue_head (&new->deathrow);
  51. INIT_LIST_HEAD (&new->lh);
  52. /* finding endpoints */
  53. for (i = 0; i < altsetting->bNumEndpoints; i++) {
  54. if (
  55.     (altsetting->endpoint[i].
  56.      bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
  57.     USB_ENDPOINT_XFER_BULK) {
  58. if (altsetting->endpoint[i].
  59.     bEndpointAddress & USB_DIR_IN) {
  60. new->ep_in =
  61. altsetting->endpoint[i].
  62. bEndpointAddress &
  63. USB_ENDPOINT_NUMBER_MASK;
  64. } else {
  65. new->ep_out =
  66. altsetting->endpoint[i].
  67. bEndpointAddress &
  68. USB_ENDPOINT_NUMBER_MASK;
  69. }
  70. } else {
  71. new->ep_int =
  72. altsetting->endpoint[i].
  73. bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
  74. new->interrupt_interval= altsetting->endpoint[i].bInterval;
  75. }
  76. }
  77. /* USB initialisation magic for the simple case */
  78. result = usb_set_interface (dev, altsetting->bInterfaceNumber, 0);
  79. switch (result) {
  80. case 0: /* no error */
  81. break;
  82. case -EPIPE:
  83. usb_clear_halt (dev, usb_sndctrlpipe (dev, 0));
  84. break;
  85. default:
  86. printk (KERN_ERR "unknown error %d from usb_set_interfacen",
  87.  result);
  88. goto err_out;
  89. }
  90. /* making a template for the scsi layer to fake detection of a scsi device */
  91. memcpy (&(new->ctempl), &hpusbscsi_scsi_host_template,
  92. sizeof (hpusbscsi_scsi_host_template));
  93. (struct hpusbscsi *) new->ctempl.proc_dir = new;
  94. new->ctempl.module = THIS_MODULE;
  95. if (scsi_register_module (MODULE_SCSI_HA, &(new->ctempl)))
  96. goto err_out;
  97. /* adding to list for module unload */
  98. list_add (&hpusbscsi_devices, &new->lh);
  99. return new;
  100.       err_out:
  101. kfree (new);
  102. return NULL;
  103. }
  104. static void
  105. hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
  106. {
  107.                  usb_unlink_urb(&(((struct hpusbscsi *) ptr)->controlurb));
  108. ((struct hpusbscsi *) ptr)->dev = NULL;
  109. }
  110. static struct usb_device_id hpusbscsi_usb_ids[] = {
  111. {USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */
  112. {USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */
  113. {USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */
  114. {} /* Terminating entry */
  115. };
  116. MODULE_DEVICE_TABLE (usb, hpusbscsi_usb_ids);
  117. MODULE_LICENSE("GPL");
  118. static struct usb_driver hpusbscsi_usb_driver = {
  119. name:"hpusbscsi",
  120. probe:hpusbscsi_usb_probe,
  121. disconnect:hpusbscsi_usb_disconnect,
  122. id_table:hpusbscsi_usb_ids,
  123. };
  124. /* module initialisation */
  125. int __init
  126. hpusbscsi_init (void)
  127. {
  128. int result;
  129. INIT_LIST_HEAD (&hpusbscsi_devices);
  130. DEBUG ("Driver loadedn");
  131. if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
  132. printk (KERN_ERR "hpusbscsi: driver registration failedn");
  133. return -1;
  134. } else {
  135. return 0;
  136. }
  137. }
  138. void __exit
  139. hpusbscsi_exit (void)
  140. {
  141. struct list_head *tmp;
  142. struct list_head *old;
  143. struct hpusbscsi * o;
  144. for (tmp = hpusbscsi_devices.next; tmp != &hpusbscsi_devices;/*nothing */) {
  145. old = tmp;
  146. tmp = tmp->next;
  147. o = (struct hpusbscsi *)old;
  148. usb_unlink_urb(&o->controlurb);
  149. scsi_unregister_module(MODULE_SCSI_HA,&o->ctempl);
  150. kfree(old);
  151. }
  152. usb_deregister (&hpusbscsi_usb_driver);
  153. }
  154. module_init (hpusbscsi_init);
  155. module_exit (hpusbscsi_exit);
  156. /* interface to the scsi layer */
  157. static int
  158. hpusbscsi_scsi_detect (struct SHT *sht)
  159. {
  160. /* Whole function stolen from usb-storage */
  161. struct hpusbscsi *desc = (struct hpusbscsi *) sht->proc_dir;
  162. /* What a hideous hack! */
  163. char local_name[48];
  164. /* set up the name of our subdirectory under /proc/scsi/ */
  165. sprintf (local_name, "hpusbscsi-%d", desc->number);
  166. sht->proc_name = kmalloc (strlen (local_name) + 1, GFP_KERNEL);
  167. /* FIXME: where is this freed ? */
  168. if (!sht->proc_name) {
  169. return 0;
  170. }
  171. strcpy (sht->proc_name, local_name);
  172. sht->proc_dir = NULL;
  173. /* build and submit an interrupt URB for status byte handling */
  174.   FILL_INT_URB(&desc->controlurb,
  175. desc->dev,
  176. usb_rcvintpipe(desc->dev,desc->ep_int),
  177. &desc->scsi_state_byte,
  178. 1,
  179. control_interrupt_callback,
  180. desc,
  181. desc->interrupt_interval
  182. );
  183. if ( 0  >  usb_submit_urb(&desc->controlurb)) {
  184. kfree(sht->proc_name);
  185. return 0;
  186. }
  187. /* In host->hostdata we store a pointer to desc */
  188. desc->host = scsi_register (sht, sizeof (desc));
  189. if (desc->host == NULL) {
  190. kfree (sht->proc_name);
  191. usb_unlink_urb(&desc->controlurb);
  192. return 0;
  193. }
  194. desc->host->hostdata[0] = (unsigned long) desc;
  195. return 1;
  196. }
  197. static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
  198. {
  199. struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
  200. usb_urb_callback usb_callback;
  201. int res;
  202. hpusbscsi->use_count++;
  203. /* we don't answer for anything but our single device on any faked host controller */
  204. if ( srb->device->lun || srb->device->id || srb->device->channel ) {
  205. if (callback) {
  206. srb->result = DID_BAD_TARGET;
  207. callback(srb);
  208. }
  209.                  goto out;
  210. }
  211. /* Now we need to decide which callback to give to the urb we send the command with */
  212. if (!srb->bufflen) {
  213. usb_callback = simple_command_callback;
  214. } else {
  215.          if (srb->use_sg) {
  216. usb_callback = scatter_gather_callback;
  217. hpusbscsi->fragment = 0;
  218. } else {
  219.                  usb_callback = simple_payload_callback;
  220. }
  221. /* Now we find out which direction data is to be transfered in */
  222. hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ?
  223. usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in)
  224. :
  225. usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out)
  226. ;
  227. }
  228. TRACE_STATE;
  229. if (hpusbscsi->state != HP_STATE_FREE) {
  230. printk(KERN_CRIT"hpusbscsi - Ouch: queueing violation!n");
  231. return 1; /* This must not happen */
  232. }
  233.         /* We zero the sense buffer to avoid confusing user space */
  234.         memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
  235. hpusbscsi->state = HP_STATE_BEGINNING;
  236. TRACE_STATE;
  237. /* We prepare the urb for writing out the scsi command */
  238. FILL_BULK_URB(
  239. &hpusbscsi->dataurb,
  240. hpusbscsi->dev,
  241. usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out),
  242. srb->cmnd,
  243. srb->cmd_len,
  244. usb_callback,
  245. hpusbscsi
  246. );
  247. hpusbscsi->scallback = callback;
  248. hpusbscsi->srb = srb;
  249. res = usb_submit_urb(&hpusbscsi->dataurb);
  250. if (res) {
  251. hpusbscsi->state = HP_STATE_FREE;
  252. TRACE_STATE;
  253. if (callback) {
  254. srb->result = DID_ERROR;
  255. callback(srb);
  256. }
  257. }
  258. out:
  259. hpusbscsi->use_count--;
  260. return 0;
  261. }
  262. static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb)
  263. {
  264. struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
  265. printk(KERN_DEBUG"SCSI reset requested.n");
  266. usb_reset_device(hpusbscsi->dev);
  267. printk(KERN_DEBUG"SCSI reset completed.n");
  268. hpusbscsi->state = HP_STATE_FREE;
  269. return 0;
  270. }
  271. static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
  272. {
  273. struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
  274. printk(KERN_DEBUG"Requested is canceled.n");
  275. usb_unlink_urb(&hpusbscsi->dataurb);
  276. usb_unlink_urb(&hpusbscsi->controlurb);
  277. hpusbscsi->state = HP_STATE_FREE;
  278. return SCSI_ABORT_PENDING;
  279. }
  280. /* usb interrupt handlers - they are all running IN INTERRUPT ! */
  281. static void handle_usb_error (struct hpusbscsi *hpusbscsi)
  282. {
  283. if (hpusbscsi->scallback != NULL) {
  284. hpusbscsi->srb->result = DID_ERROR;
  285. hpusbscsi->scallback(hpusbscsi->srb);
  286. }
  287. hpusbscsi->state = HP_STATE_FREE;
  288. }
  289. static void  control_interrupt_callback (struct urb *u)
  290. {
  291. struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
  292. DEBUG("Getting status byte %d n",hpusbscsi->scsi_state_byte);
  293. if(u->status < 0) {
  294.                 if (hpusbscsi->state != HP_STATE_FREE)
  295.                         handle_usb_error(hpusbscsi);
  296. return;
  297. }
  298. hpusbscsi->srb->result &= SCSI_ERR_MASK;
  299. hpusbscsi->srb->result |= hpusbscsi->scsi_state_byte<<1;
  300. if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT)
  301. /* we do a callback to the scsi layer if and only if all data has been transfered */
  302. hpusbscsi->scallback(hpusbscsi->srb);
  303. TRACE_STATE;
  304. switch (hpusbscsi->state) {
  305. case HP_STATE_WAIT:
  306. hpusbscsi->state = HP_STATE_FREE;
  307. TRACE_STATE;
  308. break;
  309. case HP_STATE_WORKING:
  310. case HP_STATE_BEGINNING:
  311. hpusbscsi->state = HP_STATE_PREMATURE;
  312. TRACE_STATE;
  313. break;
  314. default:
  315. printk(KERN_ERR"hpusbscsi: Unexpected status report.n");
  316. TRACE_STATE;
  317. hpusbscsi->state = HP_STATE_FREE;
  318. TRACE_STATE;
  319. break;
  320. }
  321. }
  322. static void simple_command_callback(struct urb *u)
  323. {
  324. struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
  325. if (u->status<0) {
  326. handle_usb_error(hpusbscsi);
  327. return;
  328.         }
  329. TRACE_STATE;
  330. if (hpusbscsi->state != HP_STATE_PREMATURE) {
  331.         TRACE_STATE;
  332. hpusbscsi->state = HP_STATE_WAIT;
  333. } else {
  334. if (hpusbscsi->scallback != NULL)
  335. hpusbscsi->scallback(hpusbscsi->srb);
  336. hpusbscsi->state = HP_STATE_FREE;
  337. TRACE_STATE;
  338. }
  339. }
  340. static void scatter_gather_callback(struct urb *u)
  341. {
  342. struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
  343.         struct scatterlist *sg = hpusbscsi->srb->buffer;
  344.         usb_urb_callback callback;
  345.         int res;
  346.         DEBUG("Going through scatter/gathern");
  347.         if (u->status < 0) {
  348.                 handle_usb_error(hpusbscsi);
  349.                 return;
  350.         }
  351.         if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg)
  352.                 callback = scatter_gather_callback;
  353.         else
  354.                 callback = simple_done;
  355. TRACE_STATE;
  356.         if (hpusbscsi->state != HP_STATE_PREMATURE)
  357. hpusbscsi->state = HP_STATE_WORKING;
  358. TRACE_STATE;
  359.         FILL_BULK_URB(
  360.                 u,
  361.                 hpusbscsi->dev,
  362.                 hpusbscsi->current_data_pipe,
  363.                 sg[hpusbscsi->fragment].address,
  364.                 sg[hpusbscsi->fragment++].length,
  365.                 callback,
  366.                 hpusbscsi
  367.         );
  368.         res = usb_submit_urb(u);
  369.         if (res)
  370.                 hpusbscsi->state = HP_STATE_ERROR;
  371. TRACE_STATE;
  372. }
  373. static void simple_done (struct urb *u)
  374. {
  375. struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
  376.         if (u->status < 0) {
  377.                 handle_usb_error(hpusbscsi);
  378.                 return;
  379.         }
  380.         DEBUG("Data transfer donen");
  381. TRACE_STATE;
  382. if (hpusbscsi->state != HP_STATE_PREMATURE) {
  383. if (u->status < 0)
  384. hpusbscsi->state = HP_STATE_ERROR;
  385. else
  386. hpusbscsi->state = HP_STATE_WAIT;
  387. TRACE_STATE;
  388. } else {
  389. if (hpusbscsi->scallback != NULL)
  390. hpusbscsi->scallback(hpusbscsi->srb);
  391. hpusbscsi->state = HP_STATE_FREE;
  392. }
  393. }
  394. static void simple_payload_callback (struct urb *u)
  395. {
  396. struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
  397. int res;
  398. if (u->status<0) {
  399.                 handle_usb_error(hpusbscsi);
  400. return;
  401.         }
  402. FILL_BULK_URB(
  403. u,
  404. hpusbscsi->dev,
  405. hpusbscsi->current_data_pipe,
  406. hpusbscsi->srb->buffer,
  407. hpusbscsi->srb->bufflen,
  408. simple_done,
  409. hpusbscsi
  410. );
  411. res = usb_submit_urb(u);
  412. if (res) {
  413.                 handle_usb_error(hpusbscsi);
  414. return;
  415.         }
  416. TRACE_STATE;
  417. if (hpusbscsi->state != HP_STATE_PREMATURE) {
  418. hpusbscsi->state = HP_STATE_WORKING;
  419. TRACE_STATE;
  420. } else {
  421. if (hpusbscsi->scallback != NULL)
  422. hpusbscsi->scallback(hpusbscsi->srb);
  423. hpusbscsi->state = HP_STATE_FREE;
  424. TRACE_STATE;
  425. }
  426. }