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