2 *******************************************************************************
4 ** FILE NAME : arcmsr_attr.c
6 ** Description: attributes exported to sysfs and device host
7 *******************************************************************************
8 ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
10 ** Web site: www.areca.com.tw
11 ** E-mail: support@areca.com.tw
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
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.
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 *******************************************************************************
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>
54 #include <scsi/scsi_cmnd.h>
55 #include <scsi/scsi_device.h>
56 #include <scsi/scsi_host.h>
57 #include <scsi/scsi_transport.h>
60 struct device_attribute *arcmsr_host_attrs[];
62 static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp,
64 struct bin_attribute *bin,
65 char *buf, loff_t off,
68 struct device *dev = container_of(kobj,struct device,kobj);
69 struct Scsi_Host *host = class_to_shost(dev);
70 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
71 uint8_t *pQbuffer,*ptmpQbuffer;
72 int32_t allxfer_len = 0;
75 if (!capable(CAP_SYS_ADMIN))
78 /* do message unit read. */
79 ptmpQbuffer = (uint8_t *)buf;
80 spin_lock_irqsave(&acb->rqbuffer_lock, flags);
81 if (acb->rqbuf_firstindex != acb->rqbuf_lastindex) {
82 pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
83 if (acb->rqbuf_firstindex > acb->rqbuf_lastindex) {
84 if ((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex) >= 1032) {
85 memcpy(ptmpQbuffer, pQbuffer, 1032);
86 acb->rqbuf_firstindex += 1032;
87 acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
90 if (((ARCMSR_MAX_QBUFFER - acb->rqbuf_firstindex)
91 + acb->rqbuf_lastindex) > 1032) {
92 memcpy(ptmpQbuffer, pQbuffer,
94 - acb->rqbuf_firstindex);
95 ptmpQbuffer += ARCMSR_MAX_QBUFFER
96 - acb->rqbuf_firstindex;
97 memcpy(ptmpQbuffer, acb->rqbuffer, 1032
98 - (ARCMSR_MAX_QBUFFER -
99 acb->rqbuf_firstindex));
100 acb->rqbuf_firstindex = 1032 -
101 (ARCMSR_MAX_QBUFFER -
102 acb->rqbuf_firstindex);
105 memcpy(ptmpQbuffer, pQbuffer,
107 acb->rqbuf_firstindex);
108 ptmpQbuffer += ARCMSR_MAX_QBUFFER -
109 acb->rqbuf_firstindex;
110 memcpy(ptmpQbuffer, acb->rqbuffer,
111 acb->rqbuf_lastindex);
112 allxfer_len = ARCMSR_MAX_QBUFFER -
113 acb->rqbuf_firstindex +
114 acb->rqbuf_lastindex;
115 acb->rqbuf_firstindex =
116 acb->rqbuf_lastindex;
120 if ((acb->rqbuf_lastindex - acb->rqbuf_firstindex) > 1032) {
121 memcpy(ptmpQbuffer, pQbuffer, 1032);
122 acb->rqbuf_firstindex += 1032;
125 memcpy(ptmpQbuffer, pQbuffer, acb->rqbuf_lastindex
126 - acb->rqbuf_firstindex);
127 allxfer_len = acb->rqbuf_lastindex -
128 acb->rqbuf_firstindex;
129 acb->rqbuf_firstindex = acb->rqbuf_lastindex;
133 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
134 struct QBUFFER __iomem *prbuffer;
135 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
136 prbuffer = arcmsr_get_iop_rqbuffer(acb);
137 if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
138 acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
140 spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
144 static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp,
145 struct kobject *kobj,
146 struct bin_attribute *bin,
147 char *buf, loff_t off,
150 struct device *dev = container_of(kobj,struct device,kobj);
151 struct Scsi_Host *host = class_to_shost(dev);
152 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
153 int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
154 uint8_t *pQbuffer, *ptmpuserbuffer;
157 if (!capable(CAP_SYS_ADMIN))
161 /* do message unit write. */
162 ptmpuserbuffer = (uint8_t *)buf;
163 user_len = (int32_t)count;
164 spin_lock_irqsave(&acb->wqbuffer_lock, flags);
165 wqbuf_lastindex = acb->wqbuf_lastindex;
166 wqbuf_firstindex = acb->wqbuf_firstindex;
167 if (wqbuf_lastindex != wqbuf_firstindex) {
168 arcmsr_write_ioctldata2iop(acb);
169 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
170 return 0; /*need retry*/
172 my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
173 &(ARCMSR_MAX_QBUFFER - 1);
174 if (my_empty_len >= user_len) {
175 while (user_len > 0) {
176 pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
177 memcpy(pQbuffer, ptmpuserbuffer, 1);
178 acb->wqbuf_lastindex++;
179 acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
183 if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
185 ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
186 arcmsr_write_ioctldata2iop(acb);
188 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
191 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
192 return 0; /*need retry*/
197 static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp,
198 struct kobject *kobj,
199 struct bin_attribute *bin,
200 char *buf, loff_t off,
203 struct device *dev = container_of(kobj,struct device,kobj);
204 struct Scsi_Host *host = class_to_shost(dev);
205 struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
209 if (!capable(CAP_SYS_ADMIN))
212 arcmsr_clear_iop2drv_rqueue_buffer(acb);
214 (ACB_F_MESSAGE_WQBUFFER_CLEARED
215 | ACB_F_MESSAGE_RQBUFFER_CLEARED
216 | ACB_F_MESSAGE_WQBUFFER_READED);
217 spin_lock_irqsave(&acb->rqbuffer_lock, flags);
218 acb->rqbuf_firstindex = 0;
219 acb->rqbuf_lastindex = 0;
220 spin_unlock_irqrestore(&acb->rqbuffer_lock, flags);
221 spin_lock_irqsave(&acb->wqbuffer_lock, flags);
222 acb->wqbuf_firstindex = 0;
223 acb->wqbuf_lastindex = 0;
224 spin_unlock_irqrestore(&acb->wqbuffer_lock, flags);
225 pQbuffer = acb->rqbuffer;
226 memset(pQbuffer, 0, sizeof (struct QBUFFER));
227 pQbuffer = acb->wqbuffer;
228 memset(pQbuffer, 0, sizeof (struct QBUFFER));
232 static struct bin_attribute arcmsr_sysfs_message_read_attr = {
238 .read = arcmsr_sysfs_iop_message_read,
241 static struct bin_attribute arcmsr_sysfs_message_write_attr = {
247 .write = arcmsr_sysfs_iop_message_write,
250 static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
256 .write = arcmsr_sysfs_iop_message_clear,
259 int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
261 struct Scsi_Host *host = acb->host;
264 error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
266 printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
267 goto error_bin_file_message_read;
269 error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
271 printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
272 goto error_bin_file_message_write;
274 error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
276 printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
277 goto error_bin_file_message_clear;
280 error_bin_file_message_clear:
281 sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
282 error_bin_file_message_write:
283 sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
284 error_bin_file_message_read:
288 void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb)
290 struct Scsi_Host *host = acb->host;
292 sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
293 sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
294 sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
299 arcmsr_attr_host_driver_version(struct device *dev,
300 struct device_attribute *attr, char *buf)
302 return snprintf(buf, PAGE_SIZE,
304 ARCMSR_DRIVER_VERSION);
308 arcmsr_attr_host_driver_posted_cmd(struct device *dev,
309 struct device_attribute *attr, char *buf)
311 struct Scsi_Host *host = class_to_shost(dev);
312 struct AdapterControlBlock *acb =
313 (struct AdapterControlBlock *) host->hostdata;
314 return snprintf(buf, PAGE_SIZE,
316 atomic_read(&acb->ccboutstandingcount));
320 arcmsr_attr_host_driver_reset(struct device *dev,
321 struct device_attribute *attr, char *buf)
323 struct Scsi_Host *host = class_to_shost(dev);
324 struct AdapterControlBlock *acb =
325 (struct AdapterControlBlock *) host->hostdata;
326 return snprintf(buf, PAGE_SIZE,
332 arcmsr_attr_host_driver_abort(struct device *dev,
333 struct device_attribute *attr, char *buf)
335 struct Scsi_Host *host = class_to_shost(dev);
336 struct AdapterControlBlock *acb =
337 (struct AdapterControlBlock *) host->hostdata;
338 return snprintf(buf, PAGE_SIZE,
344 arcmsr_attr_host_fw_model(struct device *dev, struct device_attribute *attr,
347 struct Scsi_Host *host = class_to_shost(dev);
348 struct AdapterControlBlock *acb =
349 (struct AdapterControlBlock *) host->hostdata;
350 return snprintf(buf, PAGE_SIZE,
356 arcmsr_attr_host_fw_version(struct device *dev,
357 struct device_attribute *attr, char *buf)
359 struct Scsi_Host *host = class_to_shost(dev);
360 struct AdapterControlBlock *acb =
361 (struct AdapterControlBlock *) host->hostdata;
363 return snprintf(buf, PAGE_SIZE,
369 arcmsr_attr_host_fw_request_len(struct device *dev,
370 struct device_attribute *attr, char *buf)
372 struct Scsi_Host *host = class_to_shost(dev);
373 struct AdapterControlBlock *acb =
374 (struct AdapterControlBlock *) host->hostdata;
376 return snprintf(buf, PAGE_SIZE,
378 acb->firm_request_len);
382 arcmsr_attr_host_fw_numbers_queue(struct device *dev,
383 struct device_attribute *attr, char *buf)
385 struct Scsi_Host *host = class_to_shost(dev);
386 struct AdapterControlBlock *acb =
387 (struct AdapterControlBlock *) host->hostdata;
389 return snprintf(buf, PAGE_SIZE,
391 acb->firm_numbers_queue);
395 arcmsr_attr_host_fw_sdram_size(struct device *dev,
396 struct device_attribute *attr, char *buf)
398 struct Scsi_Host *host = class_to_shost(dev);
399 struct AdapterControlBlock *acb =
400 (struct AdapterControlBlock *) host->hostdata;
402 return snprintf(buf, PAGE_SIZE,
404 acb->firm_sdram_size);
408 arcmsr_attr_host_fw_hd_channels(struct device *dev,
409 struct device_attribute *attr, char *buf)
411 struct Scsi_Host *host = class_to_shost(dev);
412 struct AdapterControlBlock *acb =
413 (struct AdapterControlBlock *) host->hostdata;
415 return snprintf(buf, PAGE_SIZE,
417 acb->firm_hd_channels);
420 static DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
421 static DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
422 static DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
423 static DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
424 static DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
425 static DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
426 static DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
427 static DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
428 static DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
429 static DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
431 struct device_attribute *arcmsr_host_attrs[] = {
432 &dev_attr_host_driver_version,
433 &dev_attr_host_driver_posted_cmd,
434 &dev_attr_host_driver_reset,
435 &dev_attr_host_driver_abort,
436 &dev_attr_host_fw_model,
437 &dev_attr_host_fw_version,
438 &dev_attr_host_fw_request_len,
439 &dev_attr_host_fw_numbers_queue,
440 &dev_attr_host_fw_sdram_size,
441 &dev_attr_host_fw_hd_channels,