diff options
author | andrew.vasquez@qlogic.com <andrew.vasquez@qlogic.com> | 2006-01-31 19:05:17 -0500 |
---|---|---|
committer | <jejb@mulgrave.il.steeleye.com> | 2006-02-04 17:12:41 -0500 |
commit | 854165f4245c4a3b4a8cc363ba2050033151e196 (patch) | |
tree | 0f2a19b829eaca15d3d406cfae6b77660858c7ff /drivers/scsi/qla2xxx/qla_attr.c | |
parent | 1b3f63659bd353ae460c35f5793a9fd46cc95014 (diff) |
[SCSI] qla2xxx: Add support to retrieve/update HBA option-rom.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 73d10b35091e..92b3e13e9061 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -179,6 +179,135 @@ static struct bin_attribute sysfs_nvram_attr = { | |||
179 | .write = qla2x00_sysfs_write_nvram, | 179 | .write = qla2x00_sysfs_write_nvram, |
180 | }; | 180 | }; |
181 | 181 | ||
182 | static ssize_t | ||
183 | qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, | ||
184 | size_t count) | ||
185 | { | ||
186 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | ||
187 | struct device, kobj))); | ||
188 | |||
189 | if (ha->optrom_state != QLA_SREADING) | ||
190 | return 0; | ||
191 | if (off > ha->optrom_size) | ||
192 | return 0; | ||
193 | if (off + count > ha->optrom_size) | ||
194 | count = ha->optrom_size - off; | ||
195 | |||
196 | memcpy(buf, &ha->optrom_buffer[off], count); | ||
197 | |||
198 | return count; | ||
199 | } | ||
200 | |||
201 | static ssize_t | ||
202 | qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off, | ||
203 | size_t count) | ||
204 | { | ||
205 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | ||
206 | struct device, kobj))); | ||
207 | |||
208 | if (ha->optrom_state != QLA_SWRITING) | ||
209 | return -EINVAL; | ||
210 | if (off > ha->optrom_size) | ||
211 | return -ERANGE; | ||
212 | if (off + count > ha->optrom_size) | ||
213 | count = ha->optrom_size - off; | ||
214 | |||
215 | memcpy(&ha->optrom_buffer[off], buf, count); | ||
216 | |||
217 | return count; | ||
218 | } | ||
219 | |||
220 | static struct bin_attribute sysfs_optrom_attr = { | ||
221 | .attr = { | ||
222 | .name = "optrom", | ||
223 | .mode = S_IRUSR | S_IWUSR, | ||
224 | .owner = THIS_MODULE, | ||
225 | }, | ||
226 | .size = OPTROM_SIZE_24XX, | ||
227 | .read = qla2x00_sysfs_read_optrom, | ||
228 | .write = qla2x00_sysfs_write_optrom, | ||
229 | }; | ||
230 | |||
231 | static ssize_t | ||
232 | qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, | ||
233 | size_t count) | ||
234 | { | ||
235 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | ||
236 | struct device, kobj))); | ||
237 | int val; | ||
238 | |||
239 | if (off) | ||
240 | return 0; | ||
241 | |||
242 | if (sscanf(buf, "%d", &val) != 1) | ||
243 | return -EINVAL; | ||
244 | |||
245 | switch (val) { | ||
246 | case 0: | ||
247 | if (ha->optrom_state != QLA_SREADING && | ||
248 | ha->optrom_state != QLA_SWRITING) | ||
249 | break; | ||
250 | |||
251 | ha->optrom_state = QLA_SWAITING; | ||
252 | vfree(ha->optrom_buffer); | ||
253 | ha->optrom_buffer = NULL; | ||
254 | break; | ||
255 | case 1: | ||
256 | if (ha->optrom_state != QLA_SWAITING) | ||
257 | break; | ||
258 | |||
259 | ha->optrom_state = QLA_SREADING; | ||
260 | ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); | ||
261 | if (ha->optrom_buffer == NULL) { | ||
262 | qla_printk(KERN_WARNING, ha, | ||
263 | "Unable to allocate memory for optrom retrieval " | ||
264 | "(%x).\n", ha->optrom_size); | ||
265 | |||
266 | ha->optrom_state = QLA_SWAITING; | ||
267 | return count; | ||
268 | } | ||
269 | |||
270 | memset(ha->optrom_buffer, 0, ha->optrom_size); | ||
271 | ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0, | ||
272 | ha->optrom_size); | ||
273 | break; | ||
274 | case 2: | ||
275 | if (ha->optrom_state != QLA_SWAITING) | ||
276 | break; | ||
277 | |||
278 | ha->optrom_state = QLA_SWRITING; | ||
279 | ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); | ||
280 | if (ha->optrom_buffer == NULL) { | ||
281 | qla_printk(KERN_WARNING, ha, | ||
282 | "Unable to allocate memory for optrom update " | ||
283 | "(%x).\n", ha->optrom_size); | ||
284 | |||
285 | ha->optrom_state = QLA_SWAITING; | ||
286 | return count; | ||
287 | } | ||
288 | memset(ha->optrom_buffer, 0, ha->optrom_size); | ||
289 | break; | ||
290 | case 3: | ||
291 | if (ha->optrom_state != QLA_SWRITING) | ||
292 | break; | ||
293 | |||
294 | ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0, | ||
295 | ha->optrom_size); | ||
296 | break; | ||
297 | } | ||
298 | return count; | ||
299 | } | ||
300 | |||
301 | static struct bin_attribute sysfs_optrom_ctl_attr = { | ||
302 | .attr = { | ||
303 | .name = "optrom_ctl", | ||
304 | .mode = S_IWUSR, | ||
305 | .owner = THIS_MODULE, | ||
306 | }, | ||
307 | .size = 0, | ||
308 | .write = qla2x00_sysfs_write_optrom_ctl, | ||
309 | }; | ||
310 | |||
182 | void | 311 | void |
183 | qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) | 312 | qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) |
184 | { | 313 | { |
@@ -186,6 +315,9 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) | |||
186 | 315 | ||
187 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); | 316 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); |
188 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); | 317 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); |
318 | sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); | ||
319 | sysfs_create_bin_file(&host->shost_gendev.kobj, | ||
320 | &sysfs_optrom_ctl_attr); | ||
189 | } | 321 | } |
190 | 322 | ||
191 | void | 323 | void |
@@ -195,6 +327,9 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) | |||
195 | 327 | ||
196 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); | 328 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); |
197 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); | 329 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); |
330 | sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); | ||
331 | sysfs_remove_bin_file(&host->shost_gendev.kobj, | ||
332 | &sysfs_optrom_ctl_attr); | ||
198 | 333 | ||
199 | if (ha->beacon_blink_led == 1) | 334 | if (ha->beacon_blink_led == 1) |
200 | ha->isp_ops.beacon_off(ha); | 335 | ha->isp_ops.beacon_off(ha); |