arcmsr_attr.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. *******************************************************************************
  3. ** O.S : Linux
  4. ** FILE NAME : arcmsr_attr.c
  5. ** BY : Nick Cheng
  6. ** Description: attributes exported to sysfs and device host
  7. *******************************************************************************
  8. ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
  9. **
  10. ** Web site: www.areca.com.tw
  11. ** E-mail: support@areca.com.tw
  12. **
  13. ** This program is free software; you can redistribute it and/or modify
  14. ** it under the terms of the GNU General Public License version 2 as
  15. ** published by the Free Software Foundation.
  16. ** This program is distributed in the hope that it will be useful,
  17. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. ** GNU General Public License for more details.
  20. *******************************************************************************
  21. ** Redistribution and use in source and binary forms, with or without
  22. ** modification, are permitted provided that the following conditions
  23. ** are met:
  24. ** 1. Redistributions of source code must retain the above copyright
  25. ** notice, this list of conditions and the following disclaimer.
  26. ** 2. Redistributions in binary form must reproduce the above copyright
  27. ** notice, this list of conditions and the following disclaimer in the
  28. ** documentation and/or other materials provided with the distribution.
  29. ** 3. The name of the author may not be used to endorse or promote products
  30. ** derived from this software without specific prior written permission.
  31. **
  32. ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  33. ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  34. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  35. ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  36. ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,BUT
  37. ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  38. ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY
  39. ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  40. ** (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF
  41. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. *******************************************************************************
  43. ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr
  44. ** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt
  45. *******************************************************************************
  46. */
  47. #include <linux/module.h>
  48. #include <linux/kernel.h>
  49. #include <linux/init.h>
  50. #include <linux/errno.h>
  51. #include <linux/delay.h>
  52. #include <linux/pci.h>
  53. #include <linux/circ_buf.h>
  54. #include <scsi/scsi_cmnd.h>
  55. #include <scsi/scsi_device.h>
  56. #include <scsi/scsi_host.h>
  57. #include <scsi/scsi_transport.h>
  58. #include "arcmsr.h"
  59. struct device_attribute *arcmsr_host_attrs[];
  60. static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp,
  61. struct kobject *kobj,
  62. struct bin_attribute *bin,
  63. char *buf, loff_t off,
  64. size_t count)
  65. {
  66. struct device *dev = container_of(kobj,struct device,kobj);
  67. struct Scsi_Host *host = class_to_shost(dev);
  68. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  69. uint8_t *ptmpQbuffer;
  70. int32_t allxfer_len = 0;
  71. unsigned long flags;
  72. if (!capable(CAP_SYS_ADMIN))
  73. return -EACCES;
  74. /* do message unit read. */
  75. ptmpQbuffer = (uint8_t *)buf;
  76. spin_lock_irqsave(&acb->rqbuffer_lock, flags);
  77. if (acb->rqbuf_getIndex != acb->rqbuf_putIndex) {
  78. unsigned int tail = acb->rqbuf_getIndex;
  79. unsigned int head = acb->rqbuf_putIndex;
  80. unsigned int cnt_to_end = CIRC_CNT_TO_END(head, tail, ARCMSR_MAX_QBUFFER);
  81. allxfer_len = CIRC_CNT(head, tail, ARCMSR_MAX_QBUFFER);
  82. if (allxfer_len > ARCMSR_API_DATA_BUFLEN)
  83. allxfer_len = ARCMSR_API_DATA_BUFLEN;
  84. if (allxfer_len <= cnt_to_end)
  85. memcpy(ptmpQbuffer, acb->rqbuffer + tail, allxfer_len);
  86. else {
  87. memcpy(ptmpQbuffer, acb->rqbuffer + tail, cnt_to_end);
  88. memcpy(ptmpQbuffer + cnt_to_end, acb->rqbuffer, allxfer_len - cnt_to_end);
  89. }
  90. acb->rqbuf_getIndex = (acb->rqbuf_getIndex + allxfer_len) % ARCMSR_MAX_QBUFFER;
  91. }
  92. if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
  93. struct QBUFFER __iomem *prbuffer;
  94. acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
  95. prbuffer = arcmsr_get_iop_rqbuffer(acb);
  96. if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
  97. acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
  98. }
  99. spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
  100. return allxfer_len;
  101. }
  102. static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
  103. struct kobject *kobj,
  104. struct bin_attribute *bin,
  105. char *buf, loff_t off,
  106. size_t count)
  107. {
  108. struct device *dev = container_of(kobj,struct device,kobj);
  109. struct Scsi_Host *host = class_to_shost(dev);
  110. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  111. int32_t user_len, cnt2end;
  112. uint8_t *pQbuffer, *ptmpuserbuffer;
  113. unsigned long flags;
  114. if (!capable(CAP_SYS_ADMIN))
  115. return -EACCES;
  116. if (count > ARCMSR_API_DATA_BUFLEN)
  117. return -EINVAL;
  118. /* do message unit write. */
  119. ptmpuserbuffer = (uint8_t *)buf;
  120. user_len = (int32_t)count;
  121. spin_lock_irqsave(&acb->wqbuffer_lock, flags);
  122. if (acb->wqbuf_putIndex != acb->wqbuf_getIndex) {
  123. arcmsr_write_ioctldata2iop(acb);
  124. spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
  125. return 0; /*need retry*/
  126. } else {
  127. pQbuffer = &acb->wqbuffer[acb->wqbuf_putIndex];
  128. cnt2end = ARCMSR_MAX_QBUFFER - acb->wqbuf_putIndex;
  129. if (user_len > cnt2end) {
  130. memcpy(pQbuffer, ptmpuserbuffer, cnt2end);
  131. ptmpuserbuffer += cnt2end;
  132. user_len -= cnt2end;
  133. acb->wqbuf_putIndex = 0;
  134. pQbuffer = acb->wqbuffer;
  135. }
  136. memcpy(pQbuffer, ptmpuserbuffer, user_len);
  137. acb->wqbuf_putIndex += user_len;
  138. acb->wqbuf_putIndex %= ARCMSR_MAX_QBUFFER;
  139. if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
  140. acb->acb_flags &=
  141. ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
  142. arcmsr_write_ioctldata2iop(acb);
  143. }
  144. spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
  145. return count;
  146. }
  147. }
  148. static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp,
  149. struct kobject *kobj,
  150. struct bin_attribute *bin,
  151. char *buf, loff_t off,
  152. size_t count)
  153. {
  154. struct device *dev = container_of(kobj,struct device,kobj);
  155. struct Scsi_Host *host = class_to_shost(dev);
  156. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  157. uint8_t *pQbuffer;
  158. unsigned long flags;
  159. if (!capable(CAP_SYS_ADMIN))
  160. return -EACCES;
  161. arcmsr_clear_iop2drv_rqueue_buffer(acb);
  162. acb->acb_flags |=
  163. (ACB_F_MESSAGE_WQBUFFER_CLEARED
  164. | ACB_F_MESSAGE_RQBUFFER_CLEARED
  165. | ACB_F_MESSAGE_WQBUFFER_READED);
  166. spin_lock_irqsave(&acb->rqbuffer_lock, flags);
  167. acb->rqbuf_getIndex = 0;
  168. acb->rqbuf_putIndex = 0;
  169. spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
  170. spin_lock_irqsave(&acb->wqbuffer_lock, flags);
  171. acb->wqbuf_getIndex = 0;
  172. acb->wqbuf_putIndex = 0;
  173. spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
  174. pQbuffer = acb->rqbuffer;
  175. memset(pQbuffer, 0, sizeof (struct QBUFFER));
  176. pQbuffer = acb->wqbuffer;
  177. memset(pQbuffer, 0, sizeof (struct QBUFFER));
  178. return 1;
  179. }
  180. static const struct bin_attribute arcmsr_sysfs_message_read_attr = {
  181. .attr = {
  182. .name = "mu_read",
  183. .mode = S_IRUSR ,
  184. },
  185. .size = ARCMSR_API_DATA_BUFLEN,
  186. .read = arcmsr_sysfs_iop_message_read,
  187. };
  188. static const struct bin_attribute arcmsr_sysfs_message_write_attr = {
  189. .attr = {
  190. .name = "mu_write",
  191. .mode = S_IWUSR,
  192. },
  193. .size = ARCMSR_API_DATA_BUFLEN,
  194. .write = arcmsr_sysfs_iop_message_write,
  195. };
  196. static const struct bin_attribute arcmsr_sysfs_message_clear_attr = {
  197. .attr = {
  198. .name = "mu_clear",
  199. .mode = S_IWUSR,
  200. },
  201. .size = 1,
  202. .write = arcmsr_sysfs_iop_message_clear,
  203. };
  204. int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
  205. {
  206. struct Scsi_Host *host = acb->host;
  207. int error;
  208. error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
  209. if (error) {
  210. printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
  211. goto error_bin_file_message_read;
  212. }
  213. error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
  214. if (error) {
  215. printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
  216. goto error_bin_file_message_write;
  217. }
  218. error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
  219. if (error) {
  220. printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
  221. goto error_bin_file_message_clear;
  222. }
  223. return 0;
  224. error_bin_file_message_clear:
  225. sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
  226. error_bin_file_message_write:
  227. sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
  228. error_bin_file_message_read:
  229. return error;
  230. }
  231. void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb)
  232. {
  233. struct Scsi_Host *host = acb->host;
  234. sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
  235. sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
  236. sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
  237. }
  238. static ssize_t
  239. arcmsr_attr_host_driver_version(struct device *dev,
  240. struct device_attribute *attr, char *buf)
  241. {
  242. return snprintf(buf, PAGE_SIZE,
  243. "%s\n",
  244. ARCMSR_DRIVER_VERSION);
  245. }
  246. static ssize_t
  247. arcmsr_attr_host_driver_posted_cmd(struct device *dev,
  248. struct device_attribute *attr, char *buf)
  249. {
  250. struct Scsi_Host *host = class_to_shost(dev);
  251. struct AdapterControlBlock *acb =
  252. (struct AdapterControlBlock *) host->hostdata;
  253. return snprintf(buf, PAGE_SIZE,
  254. "%4d\n",
  255. atomic_read(&acb->ccboutstandingcount));
  256. }
  257. static ssize_t
  258. arcmsr_attr_host_driver_reset(struct device *dev,
  259. struct device_attribute *attr, char *buf)
  260. {
  261. struct Scsi_Host *host = class_to_shost(dev);
  262. struct AdapterControlBlock *acb =
  263. (struct AdapterControlBlock *) host->hostdata;
  264. return snprintf(buf, PAGE_SIZE,
  265. "%4d\n",
  266. acb->num_resets);
  267. }
  268. static ssize_t
  269. arcmsr_attr_host_driver_abort(struct device *dev,
  270. struct device_attribute *attr, char *buf)
  271. {
  272. struct Scsi_Host *host = class_to_shost(dev);
  273. struct AdapterControlBlock *acb =
  274. (struct AdapterControlBlock *) host->hostdata;
  275. return snprintf(buf, PAGE_SIZE,
  276. "%4d\n",
  277. acb->num_aborts);
  278. }
  279. static ssize_t
  280. arcmsr_attr_host_fw_model(struct device *dev, struct device_attribute *attr,
  281. char *buf)
  282. {
  283. struct Scsi_Host *host = class_to_shost(dev);
  284. struct AdapterControlBlock *acb =
  285. (struct AdapterControlBlock *) host->hostdata;
  286. return snprintf(buf, PAGE_SIZE,
  287. "%s\n",
  288. acb->firm_model);
  289. }
  290. static ssize_t
  291. arcmsr_attr_host_fw_version(struct device *dev,
  292. struct device_attribute *attr, char *buf)
  293. {
  294. struct Scsi_Host *host = class_to_shost(dev);
  295. struct AdapterControlBlock *acb =
  296. (struct AdapterControlBlock *) host->hostdata;
  297. return snprintf(buf, PAGE_SIZE,
  298. "%s\n",
  299. acb->firm_version);
  300. }
  301. static ssize_t
  302. arcmsr_attr_host_fw_request_len(struct device *dev,
  303. struct device_attribute *attr, char *buf)
  304. {
  305. struct Scsi_Host *host = class_to_shost(dev);
  306. struct AdapterControlBlock *acb =
  307. (struct AdapterControlBlock *) host->hostdata;
  308. return snprintf(buf, PAGE_SIZE,
  309. "%4d\n",
  310. acb->firm_request_len);
  311. }
  312. static ssize_t
  313. arcmsr_attr_host_fw_numbers_queue(struct device *dev,
  314. struct device_attribute *attr, char *buf)
  315. {
  316. struct Scsi_Host *host = class_to_shost(dev);
  317. struct AdapterControlBlock *acb =
  318. (struct AdapterControlBlock *) host->hostdata;
  319. return snprintf(buf, PAGE_SIZE,
  320. "%4d\n",
  321. acb->firm_numbers_queue);
  322. }
  323. static ssize_t
  324. arcmsr_attr_host_fw_sdram_size(struct device *dev,
  325. struct device_attribute *attr, char *buf)
  326. {
  327. struct Scsi_Host *host = class_to_shost(dev);
  328. struct AdapterControlBlock *acb =
  329. (struct AdapterControlBlock *) host->hostdata;
  330. return snprintf(buf, PAGE_SIZE,
  331. "%4d\n",
  332. acb->firm_sdram_size);
  333. }
  334. static ssize_t
  335. arcmsr_attr_host_fw_hd_channels(struct device *dev,
  336. struct device_attribute *attr, char *buf)
  337. {
  338. struct Scsi_Host *host = class_to_shost(dev);
  339. struct AdapterControlBlock *acb =
  340. (struct AdapterControlBlock *) host->hostdata;
  341. return snprintf(buf, PAGE_SIZE,
  342. "%4d\n",
  343. acb->firm_hd_channels);
  344. }
  345. static DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
  346. static DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
  347. static DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
  348. static DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
  349. static DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
  350. static DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
  351. static DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
  352. static DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
  353. static DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
  354. static DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
  355. struct device_attribute *arcmsr_host_attrs[] = {
  356. &dev_attr_host_driver_version,
  357. &dev_attr_host_driver_posted_cmd,
  358. &dev_attr_host_driver_reset,
  359. &dev_attr_host_driver_abort,
  360. &dev_attr_host_fw_model,
  361. &dev_attr_host_fw_version,
  362. &dev_attr_host_fw_request_len,
  363. &dev_attr_host_fw_numbers_queue,
  364. &dev_attr_host_fw_sdram_size,
  365. &dev_attr_host_fw_hd_channels,
  366. NULL,
  367. };