diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic7xxx_proc.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_proc.c | 153 |
1 files changed, 44 insertions, 109 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index f2525f8ed1c7..383a3d11652d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c | |||
@@ -43,16 +43,12 @@ | |||
43 | #include "aic7xxx_inline.h" | 43 | #include "aic7xxx_inline.h" |
44 | #include "aic7xxx_93cx6.h" | 44 | #include "aic7xxx_93cx6.h" |
45 | 45 | ||
46 | static void copy_mem_info(struct info_str *info, char *data, int len); | ||
47 | static int copy_info(struct info_str *info, char *fmt, ...); | ||
48 | static void ahc_dump_target_state(struct ahc_softc *ahc, | 46 | static void ahc_dump_target_state(struct ahc_softc *ahc, |
49 | struct info_str *info, | 47 | struct seq_file *m, |
50 | u_int our_id, char channel, | 48 | u_int our_id, char channel, |
51 | u_int target_id, u_int target_offset); | 49 | u_int target_id, u_int target_offset); |
52 | static void ahc_dump_device_state(struct info_str *info, | 50 | static void ahc_dump_device_state(struct seq_file *m, |
53 | struct scsi_device *dev); | 51 | struct scsi_device *dev); |
54 | static int ahc_proc_write_seeprom(struct ahc_softc *ahc, | ||
55 | char *buffer, int length); | ||
56 | 52 | ||
57 | /* | 53 | /* |
58 | * Table of syncrates that don't follow the "divisible by 4" | 54 | * Table of syncrates that don't follow the "divisible by 4" |
@@ -94,51 +90,8 @@ ahc_calc_syncsrate(u_int period_factor) | |||
94 | return (10000000 / (period_factor * 4 * 10)); | 90 | return (10000000 / (period_factor * 4 * 10)); |
95 | } | 91 | } |
96 | 92 | ||
97 | |||
98 | static void | ||
99 | copy_mem_info(struct info_str *info, char *data, int len) | ||
100 | { | ||
101 | if (info->pos + len > info->offset + info->length) | ||
102 | len = info->offset + info->length - info->pos; | ||
103 | |||
104 | if (info->pos + len < info->offset) { | ||
105 | info->pos += len; | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | if (info->pos < info->offset) { | ||
110 | off_t partial; | ||
111 | |||
112 | partial = info->offset - info->pos; | ||
113 | data += partial; | ||
114 | info->pos += partial; | ||
115 | len -= partial; | ||
116 | } | ||
117 | |||
118 | if (len > 0) { | ||
119 | memcpy(info->buffer, data, len); | ||
120 | info->pos += len; | ||
121 | info->buffer += len; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | static int | ||
126 | copy_info(struct info_str *info, char *fmt, ...) | ||
127 | { | ||
128 | va_list args; | ||
129 | char buf[256]; | ||
130 | int len; | ||
131 | |||
132 | va_start(args, fmt); | ||
133 | len = vsprintf(buf, fmt, args); | ||
134 | va_end(args); | ||
135 | |||
136 | copy_mem_info(info, buf, len); | ||
137 | return (len); | ||
138 | } | ||
139 | |||
140 | static void | 93 | static void |
141 | ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo) | 94 | ahc_format_transinfo(struct seq_file *m, struct ahc_transinfo *tinfo) |
142 | { | 95 | { |
143 | u_int speed; | 96 | u_int speed; |
144 | u_int freq; | 97 | u_int freq; |
@@ -153,12 +106,12 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo) | |||
153 | speed *= (0x01 << tinfo->width); | 106 | speed *= (0x01 << tinfo->width); |
154 | mb = speed / 1000; | 107 | mb = speed / 1000; |
155 | if (mb > 0) | 108 | if (mb > 0) |
156 | copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000); | 109 | seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000); |
157 | else | 110 | else |
158 | copy_info(info, "%dKB/s transfers", speed); | 111 | seq_printf(m, "%dKB/s transfers", speed); |
159 | 112 | ||
160 | if (freq != 0) { | 113 | if (freq != 0) { |
161 | copy_info(info, " (%d.%03dMHz%s, offset %d", | 114 | seq_printf(m, " (%d.%03dMHz%s, offset %d", |
162 | freq / 1000, freq % 1000, | 115 | freq / 1000, freq % 1000, |
163 | (tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0 | 116 | (tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0 |
164 | ? " DT" : "", tinfo->offset); | 117 | ? " DT" : "", tinfo->offset); |
@@ -166,19 +119,19 @@ ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo) | |||
166 | 119 | ||
167 | if (tinfo->width > 0) { | 120 | if (tinfo->width > 0) { |
168 | if (freq != 0) { | 121 | if (freq != 0) { |
169 | copy_info(info, ", "); | 122 | seq_printf(m, ", "); |
170 | } else { | 123 | } else { |
171 | copy_info(info, " ("); | 124 | seq_printf(m, " ("); |
172 | } | 125 | } |
173 | copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width)); | 126 | seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width)); |
174 | } else if (freq != 0) { | 127 | } else if (freq != 0) { |
175 | copy_info(info, ")"); | 128 | seq_printf(m, ")"); |
176 | } | 129 | } |
177 | copy_info(info, "\n"); | 130 | seq_printf(m, "\n"); |
178 | } | 131 | } |
179 | 132 | ||
180 | static void | 133 | static void |
181 | ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info, | 134 | ahc_dump_target_state(struct ahc_softc *ahc, struct seq_file *m, |
182 | u_int our_id, char channel, u_int target_id, | 135 | u_int our_id, char channel, u_int target_id, |
183 | u_int target_offset) | 136 | u_int target_offset) |
184 | { | 137 | { |
@@ -190,18 +143,18 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info, | |||
190 | tinfo = ahc_fetch_transinfo(ahc, channel, our_id, | 143 | tinfo = ahc_fetch_transinfo(ahc, channel, our_id, |
191 | target_id, &tstate); | 144 | target_id, &tstate); |
192 | if ((ahc->features & AHC_TWIN) != 0) | 145 | if ((ahc->features & AHC_TWIN) != 0) |
193 | copy_info(info, "Channel %c ", channel); | 146 | seq_printf(m, "Channel %c ", channel); |
194 | copy_info(info, "Target %d Negotiation Settings\n", target_id); | 147 | seq_printf(m, "Target %d Negotiation Settings\n", target_id); |
195 | copy_info(info, "\tUser: "); | 148 | seq_printf(m, "\tUser: "); |
196 | ahc_format_transinfo(info, &tinfo->user); | 149 | ahc_format_transinfo(m, &tinfo->user); |
197 | starget = ahc->platform_data->starget[target_offset]; | 150 | starget = ahc->platform_data->starget[target_offset]; |
198 | if (!starget) | 151 | if (!starget) |
199 | return; | 152 | return; |
200 | 153 | ||
201 | copy_info(info, "\tGoal: "); | 154 | seq_printf(m, "\tGoal: "); |
202 | ahc_format_transinfo(info, &tinfo->goal); | 155 | ahc_format_transinfo(m, &tinfo->goal); |
203 | copy_info(info, "\tCurr: "); | 156 | seq_printf(m, "\tCurr: "); |
204 | ahc_format_transinfo(info, &tinfo->curr); | 157 | ahc_format_transinfo(m, &tinfo->curr); |
205 | 158 | ||
206 | for (lun = 0; lun < AHC_NUM_LUNS; lun++) { | 159 | for (lun = 0; lun < AHC_NUM_LUNS; lun++) { |
207 | struct scsi_device *sdev; | 160 | struct scsi_device *sdev; |
@@ -211,29 +164,30 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info, | |||
211 | if (sdev == NULL) | 164 | if (sdev == NULL) |
212 | continue; | 165 | continue; |
213 | 166 | ||
214 | ahc_dump_device_state(info, sdev); | 167 | ahc_dump_device_state(m, sdev); |
215 | } | 168 | } |
216 | } | 169 | } |
217 | 170 | ||
218 | static void | 171 | static void |
219 | ahc_dump_device_state(struct info_str *info, struct scsi_device *sdev) | 172 | ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev) |
220 | { | 173 | { |
221 | struct ahc_linux_device *dev = scsi_transport_device_data(sdev); | 174 | struct ahc_linux_device *dev = scsi_transport_device_data(sdev); |
222 | 175 | ||
223 | copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", | 176 | seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n", |
224 | sdev->sdev_target->channel + 'A', | 177 | sdev->sdev_target->channel + 'A', |
225 | sdev->sdev_target->id, sdev->lun); | 178 | sdev->sdev_target->id, sdev->lun); |
226 | 179 | ||
227 | copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); | 180 | seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued); |
228 | copy_info(info, "\t\tCommands Active %d\n", dev->active); | 181 | seq_printf(m, "\t\tCommands Active %d\n", dev->active); |
229 | copy_info(info, "\t\tCommand Openings %d\n", dev->openings); | 182 | seq_printf(m, "\t\tCommand Openings %d\n", dev->openings); |
230 | copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags); | 183 | seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags); |
231 | copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen); | 184 | seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen); |
232 | } | 185 | } |
233 | 186 | ||
234 | static int | 187 | int |
235 | ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length) | 188 | ahc_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length) |
236 | { | 189 | { |
190 | struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata; | ||
237 | struct seeprom_descriptor sd; | 191 | struct seeprom_descriptor sd; |
238 | int have_seeprom; | 192 | int have_seeprom; |
239 | u_long s; | 193 | u_long s; |
@@ -332,53 +286,36 @@ done: | |||
332 | * Return information to handle /proc support for the driver. | 286 | * Return information to handle /proc support for the driver. |
333 | */ | 287 | */ |
334 | int | 288 | int |
335 | ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | 289 | ahc_linux_show_info(struct seq_file *m, struct Scsi_Host *shost) |
336 | off_t offset, int length, int inout) | ||
337 | { | 290 | { |
338 | struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata; | 291 | struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata; |
339 | struct info_str info; | ||
340 | char ahc_info[256]; | 292 | char ahc_info[256]; |
341 | u_int max_targ; | 293 | u_int max_targ; |
342 | u_int i; | 294 | u_int i; |
343 | int retval; | ||
344 | 295 | ||
345 | /* Has data been written to the file? */ | 296 | seq_printf(m, "Adaptec AIC7xxx driver version: %s\n", |
346 | if (inout == TRUE) { | ||
347 | retval = ahc_proc_write_seeprom(ahc, buffer, length); | ||
348 | goto done; | ||
349 | } | ||
350 | |||
351 | if (start) | ||
352 | *start = buffer; | ||
353 | |||
354 | info.buffer = buffer; | ||
355 | info.length = length; | ||
356 | info.offset = offset; | ||
357 | info.pos = 0; | ||
358 | |||
359 | copy_info(&info, "Adaptec AIC7xxx driver version: %s\n", | ||
360 | AIC7XXX_DRIVER_VERSION); | 297 | AIC7XXX_DRIVER_VERSION); |
361 | copy_info(&info, "%s\n", ahc->description); | 298 | seq_printf(m, "%s\n", ahc->description); |
362 | ahc_controller_info(ahc, ahc_info); | 299 | ahc_controller_info(ahc, ahc_info); |
363 | copy_info(&info, "%s\n", ahc_info); | 300 | seq_printf(m, "%s\n", ahc_info); |
364 | copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n", | 301 | seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n", |
365 | ahc->scb_data->numscbs, AHC_NSEG); | 302 | ahc->scb_data->numscbs, AHC_NSEG); |
366 | 303 | ||
367 | 304 | ||
368 | if (ahc->seep_config == NULL) | 305 | if (ahc->seep_config == NULL) |
369 | copy_info(&info, "No Serial EEPROM\n"); | 306 | seq_printf(m, "No Serial EEPROM\n"); |
370 | else { | 307 | else { |
371 | copy_info(&info, "Serial EEPROM:\n"); | 308 | seq_printf(m, "Serial EEPROM:\n"); |
372 | for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) { | 309 | for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) { |
373 | if (((i % 8) == 0) && (i != 0)) { | 310 | if (((i % 8) == 0) && (i != 0)) { |
374 | copy_info(&info, "\n"); | 311 | seq_printf(m, "\n"); |
375 | } | 312 | } |
376 | copy_info(&info, "0x%.4x ", | 313 | seq_printf(m, "0x%.4x ", |
377 | ((uint16_t*)ahc->seep_config)[i]); | 314 | ((uint16_t*)ahc->seep_config)[i]); |
378 | } | 315 | } |
379 | copy_info(&info, "\n"); | 316 | seq_printf(m, "\n"); |
380 | } | 317 | } |
381 | copy_info(&info, "\n"); | 318 | seq_printf(m, "\n"); |
382 | 319 | ||
383 | max_targ = 16; | 320 | max_targ = 16; |
384 | if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) | 321 | if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) |
@@ -398,10 +335,8 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | |||
398 | target_id = i % 8; | 335 | target_id = i % 8; |
399 | } | 336 | } |
400 | 337 | ||
401 | ahc_dump_target_state(ahc, &info, our_id, | 338 | ahc_dump_target_state(ahc, m, our_id, |
402 | channel, target_id, i); | 339 | channel, target_id, i); |
403 | } | 340 | } |
404 | retval = info.pos > info.offset ? info.pos - info.offset : 0; | 341 | return 0; |
405 | done: | ||
406 | return (retval); | ||
407 | } | 342 | } |