arcmsr_attr.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. *******************************************************************************
  3. ** O.S : Linux
  4. ** FILE NAME : arcmsr_attr.c
  5. ** BY : Erich Chen
  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: erich@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 <scsi/scsi_cmnd.h>
  54. #include <scsi/scsi_device.h>
  55. #include <scsi/scsi_host.h>
  56. #include <scsi/scsi_transport.h>
  57. #include "arcmsr.h"
  58. struct class_device_attribute *arcmsr_host_attrs[];
  59. static ssize_t
  60. arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
  61. size_t count)
  62. {
  63. struct class_device *cdev = container_of(kobj,struct class_device,kobj);
  64. struct Scsi_Host *host = class_to_shost(cdev);
  65. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  66. struct MessageUnit __iomem *reg = acb->pmu;
  67. uint8_t *pQbuffer,*ptmpQbuffer;
  68. int32_t allxfer_len = 0;
  69. if (!capable(CAP_SYS_ADMIN))
  70. return -EACCES;
  71. /* do message unit read. */
  72. ptmpQbuffer = (uint8_t *)buf;
  73. while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
  74. && (allxfer_len < 1031)) {
  75. pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
  76. memcpy(ptmpQbuffer, pQbuffer, 1);
  77. acb->rqbuf_firstindex++;
  78. acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
  79. ptmpQbuffer++;
  80. allxfer_len++;
  81. }
  82. if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
  83. struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *)
  84. &reg->message_rbuffer;
  85. uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data;
  86. int32_t iop_len;
  87. acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
  88. iop_len = readl(&prbuffer->data_len);
  89. while (iop_len > 0) {
  90. acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
  91. acb->rqbuf_lastindex++;
  92. acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
  93. iop_data++;
  94. iop_len--;
  95. }
  96. writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
  97. &reg->inbound_doorbell);
  98. }
  99. return (allxfer_len);
  100. }
  101. static ssize_t
  102. arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
  103. size_t count)
  104. {
  105. struct class_device *cdev = container_of(kobj,struct class_device,kobj);
  106. struct Scsi_Host *host = class_to_shost(cdev);
  107. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  108. int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
  109. uint8_t *pQbuffer, *ptmpuserbuffer;
  110. if (!capable(CAP_SYS_ADMIN))
  111. return -EACCES;
  112. if (count > 1032)
  113. return -EINVAL;
  114. /* do message unit write. */
  115. ptmpuserbuffer = (uint8_t *)buf;
  116. user_len = (int32_t)count;
  117. wqbuf_lastindex = acb->wqbuf_lastindex;
  118. wqbuf_firstindex = acb->wqbuf_firstindex;
  119. if (wqbuf_lastindex != wqbuf_firstindex) {
  120. arcmsr_post_Qbuffer(acb);
  121. return 0; /*need retry*/
  122. } else {
  123. my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
  124. &(ARCMSR_MAX_QBUFFER - 1);
  125. if (my_empty_len >= user_len) {
  126. while (user_len > 0) {
  127. pQbuffer =
  128. &acb->wqbuffer[acb->wqbuf_lastindex];
  129. memcpy(pQbuffer, ptmpuserbuffer, 1);
  130. acb->wqbuf_lastindex++;
  131. acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
  132. ptmpuserbuffer++;
  133. user_len--;
  134. }
  135. if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
  136. acb->acb_flags &=
  137. ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
  138. arcmsr_post_Qbuffer(acb);
  139. }
  140. return count;
  141. } else {
  142. return 0; /*need retry*/
  143. }
  144. }
  145. }
  146. static ssize_t
  147. arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off,
  148. size_t count)
  149. {
  150. struct class_device *cdev = container_of(kobj,struct class_device,kobj);
  151. struct Scsi_Host *host = class_to_shost(cdev);
  152. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  153. struct MessageUnit __iomem *reg = acb->pmu;
  154. uint8_t *pQbuffer;
  155. if (!capable(CAP_SYS_ADMIN))
  156. return -EACCES;
  157. if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
  158. acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
  159. writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK
  160. , &reg->inbound_doorbell);
  161. }
  162. acb->acb_flags |=
  163. (ACB_F_MESSAGE_WQBUFFER_CLEARED
  164. | ACB_F_MESSAGE_RQBUFFER_CLEARED
  165. | ACB_F_MESSAGE_WQBUFFER_READED);
  166. acb->rqbuf_firstindex = 0;
  167. acb->rqbuf_lastindex = 0;
  168. acb->wqbuf_firstindex = 0;
  169. acb->wqbuf_lastindex = 0;
  170. pQbuffer = acb->rqbuffer;
  171. memset(pQbuffer, 0, sizeof (struct QBUFFER));
  172. pQbuffer = acb->wqbuffer;
  173. memset(pQbuffer, 0, sizeof (struct QBUFFER));
  174. return 1;
  175. }
  176. static struct bin_attribute arcmsr_sysfs_message_read_attr = {
  177. .attr = {
  178. .name = "mu_read",
  179. .mode = S_IRUSR ,
  180. .owner = THIS_MODULE,
  181. },
  182. .size = 1032,
  183. .read = arcmsr_sysfs_iop_message_read,
  184. };
  185. static struct bin_attribute arcmsr_sysfs_message_write_attr = {
  186. .attr = {
  187. .name = "mu_write",
  188. .mode = S_IWUSR,
  189. .owner = THIS_MODULE,
  190. },
  191. .size = 1032,
  192. .write = arcmsr_sysfs_iop_message_write,
  193. };
  194. static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
  195. .attr = {
  196. .name = "mu_clear",
  197. .mode = S_IWUSR,
  198. .owner = THIS_MODULE,
  199. },
  200. .size = 1,
  201. .write = arcmsr_sysfs_iop_message_clear,
  202. };
  203. int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
  204. {
  205. struct Scsi_Host *host = acb->host;
  206. int error;
  207. error = sysfs_create_bin_file(&host->shost_classdev.kobj,
  208. &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_classdev.kobj,
  214. &arcmsr_sysfs_message_write_attr);
  215. if (error) {
  216. printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
  217. goto error_bin_file_message_write;
  218. }
  219. error = sysfs_create_bin_file(&host->shost_classdev.kobj,
  220. &arcmsr_sysfs_message_clear_attr);
  221. if (error) {
  222. printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
  223. goto error_bin_file_message_clear;
  224. }
  225. return 0;
  226. error_bin_file_message_clear:
  227. sysfs_remove_bin_file(&host->shost_classdev.kobj,
  228. &arcmsr_sysfs_message_write_attr);
  229. error_bin_file_message_write:
  230. sysfs_remove_bin_file(&host->shost_classdev.kobj,
  231. &arcmsr_sysfs_message_read_attr);
  232. error_bin_file_message_read:
  233. return error;
  234. }
  235. void
  236. arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
  237. struct Scsi_Host *host = acb->host;
  238. sysfs_remove_bin_file(&host->shost_classdev.kobj,
  239. &arcmsr_sysfs_message_clear_attr);
  240. sysfs_remove_bin_file(&host->shost_classdev.kobj,
  241. &arcmsr_sysfs_message_write_attr);
  242. sysfs_remove_bin_file(&host->shost_classdev.kobj,
  243. &arcmsr_sysfs_message_read_attr);
  244. }
  245. static ssize_t
  246. arcmsr_attr_host_driver_version(struct class_device *cdev, char *buf) {
  247. return snprintf(buf, PAGE_SIZE,
  248. "%s\n",
  249. ARCMSR_DRIVER_VERSION);
  250. }
  251. static ssize_t
  252. arcmsr_attr_host_driver_posted_cmd(struct class_device *cdev, char *buf) {
  253. struct Scsi_Host *host = class_to_shost(cdev);
  254. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  255. return snprintf(buf, PAGE_SIZE,
  256. "%4d\n",
  257. atomic_read(&acb->ccboutstandingcount));
  258. }
  259. static ssize_t
  260. arcmsr_attr_host_driver_reset(struct class_device *cdev, char *buf) {
  261. struct Scsi_Host *host = class_to_shost(cdev);
  262. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  263. return snprintf(buf, PAGE_SIZE,
  264. "%4d\n",
  265. acb->num_resets);
  266. }
  267. static ssize_t
  268. arcmsr_attr_host_driver_abort(struct class_device *cdev, char *buf) {
  269. struct Scsi_Host *host = class_to_shost(cdev);
  270. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  271. return snprintf(buf, PAGE_SIZE,
  272. "%4d\n",
  273. acb->num_aborts);
  274. }
  275. static ssize_t
  276. arcmsr_attr_host_fw_model(struct class_device *cdev, char *buf) {
  277. struct Scsi_Host *host = class_to_shost(cdev);
  278. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  279. return snprintf(buf, PAGE_SIZE,
  280. "%s\n",
  281. acb->firm_model);
  282. }
  283. static ssize_t
  284. arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
  285. struct Scsi_Host *host = class_to_shost(cdev);
  286. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  287. return snprintf(buf, PAGE_SIZE,
  288. "%s\n",
  289. acb->firm_version);
  290. }
  291. static ssize_t
  292. arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) {
  293. struct Scsi_Host *host = class_to_shost(cdev);
  294. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  295. return snprintf(buf, PAGE_SIZE,
  296. "%4d\n",
  297. acb->firm_request_len);
  298. }
  299. static ssize_t
  300. arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
  301. struct Scsi_Host *host = class_to_shost(cdev);
  302. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  303. return snprintf(buf, PAGE_SIZE,
  304. "%4d\n",
  305. acb->firm_numbers_queue);
  306. }
  307. static ssize_t
  308. arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) {
  309. struct Scsi_Host *host = class_to_shost(cdev);
  310. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  311. return snprintf(buf, PAGE_SIZE,
  312. "%4d\n",
  313. acb->firm_sdram_size);
  314. }
  315. static ssize_t
  316. arcmsr_attr_host_fw_hd_channels(struct class_device *cdev, char *buf) {
  317. struct Scsi_Host *host = class_to_shost(cdev);
  318. struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
  319. return snprintf(buf, PAGE_SIZE,
  320. "%4d\n",
  321. acb->firm_hd_channels);
  322. }
  323. static CLASS_DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
  324. static CLASS_DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
  325. static CLASS_DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
  326. static CLASS_DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
  327. static CLASS_DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
  328. static CLASS_DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
  329. static CLASS_DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
  330. static CLASS_DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
  331. static CLASS_DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
  332. static CLASS_DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
  333. struct class_device_attribute *arcmsr_host_attrs[] = {
  334. &class_device_attr_host_driver_version,
  335. &class_device_attr_host_driver_posted_cmd,
  336. &class_device_attr_host_driver_reset,
  337. &class_device_attr_host_driver_abort,
  338. &class_device_attr_host_fw_model,
  339. &class_device_attr_host_fw_version,
  340. &class_device_attr_host_fw_request_len,
  341. &class_device_attr_host_fw_numbers_queue,
  342. &class_device_attr_host_fw_sdram_size,
  343. &class_device_attr_host_fw_hd_channels,
  344. NULL,
  345. };