diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_proc.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_proc.c | 163 |
1 files changed, 49 insertions, 114 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index 59c85d5a153a..e9778b4f7e32 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c | |||
@@ -42,16 +42,12 @@ | |||
42 | #include "aic79xx_osm.h" | 42 | #include "aic79xx_osm.h" |
43 | #include "aic79xx_inline.h" | 43 | #include "aic79xx_inline.h" |
44 | 44 | ||
45 | static void copy_mem_info(struct info_str *info, char *data, int len); | ||
46 | static int copy_info(struct info_str *info, char *fmt, ...); | ||
47 | static void ahd_dump_target_state(struct ahd_softc *ahd, | 45 | static void ahd_dump_target_state(struct ahd_softc *ahd, |
48 | struct info_str *info, | 46 | struct seq_file *m, |
49 | u_int our_id, char channel, | 47 | u_int our_id, char channel, |
50 | u_int target_id); | 48 | u_int target_id); |
51 | static void ahd_dump_device_state(struct info_str *info, | 49 | static void ahd_dump_device_state(struct seq_file *m, |
52 | struct scsi_device *sdev); | 50 | struct scsi_device *sdev); |
53 | static int ahd_proc_write_seeprom(struct ahd_softc *ahd, | ||
54 | char *buffer, int length); | ||
55 | 51 | ||
56 | /* | 52 | /* |
57 | * Table of syncrates that don't follow the "divisible by 4" | 53 | * Table of syncrates that don't follow the "divisible by 4" |
@@ -93,58 +89,15 @@ ahd_calc_syncsrate(u_int period_factor) | |||
93 | return (10000000 / (period_factor * 4 * 10)); | 89 | return (10000000 / (period_factor * 4 * 10)); |
94 | } | 90 | } |
95 | 91 | ||
96 | |||
97 | static void | ||
98 | copy_mem_info(struct info_str *info, char *data, int len) | ||
99 | { | ||
100 | if (info->pos + len > info->offset + info->length) | ||
101 | len = info->offset + info->length - info->pos; | ||
102 | |||
103 | if (info->pos + len < info->offset) { | ||
104 | info->pos += len; | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | if (info->pos < info->offset) { | ||
109 | off_t partial; | ||
110 | |||
111 | partial = info->offset - info->pos; | ||
112 | data += partial; | ||
113 | info->pos += partial; | ||
114 | len -= partial; | ||
115 | } | ||
116 | |||
117 | if (len > 0) { | ||
118 | memcpy(info->buffer, data, len); | ||
119 | info->pos += len; | ||
120 | info->buffer += len; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static int | ||
125 | copy_info(struct info_str *info, char *fmt, ...) | ||
126 | { | ||
127 | va_list args; | ||
128 | char buf[256]; | ||
129 | int len; | ||
130 | |||
131 | va_start(args, fmt); | ||
132 | len = vsprintf(buf, fmt, args); | ||
133 | va_end(args); | ||
134 | |||
135 | copy_mem_info(info, buf, len); | ||
136 | return (len); | ||
137 | } | ||
138 | |||
139 | static void | 92 | static void |
140 | ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) | 93 | ahd_format_transinfo(struct seq_file *m, struct ahd_transinfo *tinfo) |
141 | { | 94 | { |
142 | u_int speed; | 95 | u_int speed; |
143 | u_int freq; | 96 | u_int freq; |
144 | u_int mb; | 97 | u_int mb; |
145 | 98 | ||
146 | if (tinfo->period == AHD_PERIOD_UNKNOWN) { | 99 | if (tinfo->period == AHD_PERIOD_UNKNOWN) { |
147 | copy_info(info, "Renegotiation Pending\n"); | 100 | seq_printf(m, "Renegotiation Pending\n"); |
148 | return; | 101 | return; |
149 | } | 102 | } |
150 | speed = 3300; | 103 | speed = 3300; |
@@ -156,34 +109,34 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) | |||
156 | speed *= (0x01 << tinfo->width); | 109 | speed *= (0x01 << tinfo->width); |
157 | mb = speed / 1000; | 110 | mb = speed / 1000; |
158 | if (mb > 0) | 111 | if (mb > 0) |
159 | copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000); | 112 | seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000); |
160 | else | 113 | else |
161 | copy_info(info, "%dKB/s transfers", speed); | 114 | seq_printf(m, "%dKB/s transfers", speed); |
162 | 115 | ||
163 | if (freq != 0) { | 116 | if (freq != 0) { |
164 | int printed_options; | 117 | int printed_options; |
165 | 118 | ||
166 | printed_options = 0; | 119 | printed_options = 0; |
167 | copy_info(info, " (%d.%03dMHz", freq / 1000, freq % 1000); | 120 | seq_printf(m, " (%d.%03dMHz", freq / 1000, freq % 1000); |
168 | if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) { | 121 | if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) { |
169 | copy_info(info, " RDSTRM"); | 122 | seq_printf(m, " RDSTRM"); |
170 | printed_options++; | 123 | printed_options++; |
171 | } | 124 | } |
172 | if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { | 125 | if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { |
173 | copy_info(info, "%s", printed_options ? "|DT" : " DT"); | 126 | seq_printf(m, "%s", printed_options ? "|DT" : " DT"); |
174 | printed_options++; | 127 | printed_options++; |
175 | } | 128 | } |
176 | if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { | 129 | if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { |
177 | copy_info(info, "%s", printed_options ? "|IU" : " IU"); | 130 | seq_printf(m, "%s", printed_options ? "|IU" : " IU"); |
178 | printed_options++; | 131 | printed_options++; |
179 | } | 132 | } |
180 | if ((tinfo->ppr_options & MSG_EXT_PPR_RTI) != 0) { | 133 | if ((tinfo->ppr_options & MSG_EXT_PPR_RTI) != 0) { |
181 | copy_info(info, "%s", | 134 | seq_printf(m, "%s", |
182 | printed_options ? "|RTI" : " RTI"); | 135 | printed_options ? "|RTI" : " RTI"); |
183 | printed_options++; | 136 | printed_options++; |
184 | } | 137 | } |
185 | if ((tinfo->ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) { | 138 | if ((tinfo->ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) { |
186 | copy_info(info, "%s", | 139 | seq_printf(m, "%s", |
187 | printed_options ? "|QAS" : " QAS"); | 140 | printed_options ? "|QAS" : " QAS"); |
188 | printed_options++; | 141 | printed_options++; |
189 | } | 142 | } |
@@ -191,19 +144,19 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) | |||
191 | 144 | ||
192 | if (tinfo->width > 0) { | 145 | if (tinfo->width > 0) { |
193 | if (freq != 0) { | 146 | if (freq != 0) { |
194 | copy_info(info, ", "); | 147 | seq_printf(m, ", "); |
195 | } else { | 148 | } else { |
196 | copy_info(info, " ("); | 149 | seq_printf(m, " ("); |
197 | } | 150 | } |
198 | copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width)); | 151 | seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width)); |
199 | } else if (freq != 0) { | 152 | } else if (freq != 0) { |
200 | copy_info(info, ")"); | 153 | seq_printf(m, ")"); |
201 | } | 154 | } |
202 | copy_info(info, "\n"); | 155 | seq_printf(m, "\n"); |
203 | } | 156 | } |
204 | 157 | ||
205 | static void | 158 | static void |
206 | ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | 159 | ahd_dump_target_state(struct ahd_softc *ahd, struct seq_file *m, |
207 | u_int our_id, char channel, u_int target_id) | 160 | u_int our_id, char channel, u_int target_id) |
208 | { | 161 | { |
209 | struct scsi_target *starget; | 162 | struct scsi_target *starget; |
@@ -213,17 +166,17 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
213 | 166 | ||
214 | tinfo = ahd_fetch_transinfo(ahd, channel, our_id, | 167 | tinfo = ahd_fetch_transinfo(ahd, channel, our_id, |
215 | target_id, &tstate); | 168 | target_id, &tstate); |
216 | copy_info(info, "Target %d Negotiation Settings\n", target_id); | 169 | seq_printf(m, "Target %d Negotiation Settings\n", target_id); |
217 | copy_info(info, "\tUser: "); | 170 | seq_printf(m, "\tUser: "); |
218 | ahd_format_transinfo(info, &tinfo->user); | 171 | ahd_format_transinfo(m, &tinfo->user); |
219 | starget = ahd->platform_data->starget[target_id]; | 172 | starget = ahd->platform_data->starget[target_id]; |
220 | if (starget == NULL) | 173 | if (starget == NULL) |
221 | return; | 174 | return; |
222 | 175 | ||
223 | copy_info(info, "\tGoal: "); | 176 | seq_printf(m, "\tGoal: "); |
224 | ahd_format_transinfo(info, &tinfo->goal); | 177 | ahd_format_transinfo(m, &tinfo->goal); |
225 | copy_info(info, "\tCurr: "); | 178 | seq_printf(m, "\tCurr: "); |
226 | ahd_format_transinfo(info, &tinfo->curr); | 179 | ahd_format_transinfo(m, &tinfo->curr); |
227 | 180 | ||
228 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { | 181 | for (lun = 0; lun < AHD_NUM_LUNS; lun++) { |
229 | struct scsi_device *dev; | 182 | struct scsi_device *dev; |
@@ -233,29 +186,30 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, | |||
233 | if (dev == NULL) | 186 | if (dev == NULL) |
234 | continue; | 187 | continue; |
235 | 188 | ||
236 | ahd_dump_device_state(info, dev); | 189 | ahd_dump_device_state(m, dev); |
237 | } | 190 | } |
238 | } | 191 | } |
239 | 192 | ||
240 | static void | 193 | static void |
241 | ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev) | 194 | ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev) |
242 | { | 195 | { |
243 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); | 196 | struct ahd_linux_device *dev = scsi_transport_device_data(sdev); |
244 | 197 | ||
245 | copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", | 198 | seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n", |
246 | sdev->sdev_target->channel + 'A', | 199 | sdev->sdev_target->channel + 'A', |
247 | sdev->sdev_target->id, sdev->lun); | 200 | sdev->sdev_target->id, sdev->lun); |
248 | 201 | ||
249 | copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); | 202 | seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued); |
250 | copy_info(info, "\t\tCommands Active %d\n", dev->active); | 203 | seq_printf(m, "\t\tCommands Active %d\n", dev->active); |
251 | copy_info(info, "\t\tCommand Openings %d\n", dev->openings); | 204 | seq_printf(m, "\t\tCommand Openings %d\n", dev->openings); |
252 | copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags); | 205 | seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags); |
253 | copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen); | 206 | seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen); |
254 | } | 207 | } |
255 | 208 | ||
256 | static int | 209 | int |
257 | ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length) | 210 | ahd_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length) |
258 | { | 211 | { |
212 | struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata; | ||
259 | ahd_mode_state saved_modes; | 213 | ahd_mode_state saved_modes; |
260 | int have_seeprom; | 214 | int have_seeprom; |
261 | u_long s; | 215 | u_long s; |
@@ -319,64 +273,45 @@ done: | |||
319 | * Return information to handle /proc support for the driver. | 273 | * Return information to handle /proc support for the driver. |
320 | */ | 274 | */ |
321 | int | 275 | int |
322 | ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | 276 | ahd_linux_show_info(struct seq_file *m, struct Scsi_Host *shost) |
323 | off_t offset, int length, int inout) | ||
324 | { | 277 | { |
325 | struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata; | 278 | struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata; |
326 | struct info_str info; | ||
327 | char ahd_info[256]; | 279 | char ahd_info[256]; |
328 | u_int max_targ; | 280 | u_int max_targ; |
329 | u_int i; | 281 | u_int i; |
330 | int retval; | ||
331 | 282 | ||
332 | /* Has data been written to the file? */ | 283 | seq_printf(m, "Adaptec AIC79xx driver version: %s\n", |
333 | if (inout == TRUE) { | ||
334 | retval = ahd_proc_write_seeprom(ahd, buffer, length); | ||
335 | goto done; | ||
336 | } | ||
337 | |||
338 | if (start) | ||
339 | *start = buffer; | ||
340 | |||
341 | info.buffer = buffer; | ||
342 | info.length = length; | ||
343 | info.offset = offset; | ||
344 | info.pos = 0; | ||
345 | |||
346 | copy_info(&info, "Adaptec AIC79xx driver version: %s\n", | ||
347 | AIC79XX_DRIVER_VERSION); | 284 | AIC79XX_DRIVER_VERSION); |
348 | copy_info(&info, "%s\n", ahd->description); | 285 | seq_printf(m, "%s\n", ahd->description); |
349 | ahd_controller_info(ahd, ahd_info); | 286 | ahd_controller_info(ahd, ahd_info); |
350 | copy_info(&info, "%s\n", ahd_info); | 287 | seq_printf(m, "%s\n", ahd_info); |
351 | copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n", | 288 | seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n", |
352 | ahd->scb_data.numscbs, AHD_NSEG); | 289 | ahd->scb_data.numscbs, AHD_NSEG); |
353 | 290 | ||
354 | max_targ = 16; | 291 | max_targ = 16; |
355 | 292 | ||
356 | if (ahd->seep_config == NULL) | 293 | if (ahd->seep_config == NULL) |
357 | copy_info(&info, "No Serial EEPROM\n"); | 294 | seq_printf(m, "No Serial EEPROM\n"); |
358 | else { | 295 | else { |
359 | copy_info(&info, "Serial EEPROM:\n"); | 296 | seq_printf(m, "Serial EEPROM:\n"); |
360 | for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) { | 297 | for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) { |
361 | if (((i % 8) == 0) && (i != 0)) { | 298 | if (((i % 8) == 0) && (i != 0)) { |
362 | copy_info(&info, "\n"); | 299 | seq_printf(m, "\n"); |
363 | } | 300 | } |
364 | copy_info(&info, "0x%.4x ", | 301 | seq_printf(m, "0x%.4x ", |
365 | ((uint16_t*)ahd->seep_config)[i]); | 302 | ((uint16_t*)ahd->seep_config)[i]); |
366 | } | 303 | } |
367 | copy_info(&info, "\n"); | 304 | seq_printf(m, "\n"); |
368 | } | 305 | } |
369 | copy_info(&info, "\n"); | 306 | seq_printf(m, "\n"); |
370 | 307 | ||
371 | if ((ahd->features & AHD_WIDE) == 0) | 308 | if ((ahd->features & AHD_WIDE) == 0) |
372 | max_targ = 8; | 309 | max_targ = 8; |
373 | 310 | ||
374 | for (i = 0; i < max_targ; i++) { | 311 | for (i = 0; i < max_targ; i++) { |
375 | 312 | ||
376 | ahd_dump_target_state(ahd, &info, ahd->our_id, 'A', | 313 | ahd_dump_target_state(ahd, m, ahd->our_id, 'A', |
377 | /*target_id*/i); | 314 | /*target_id*/i); |
378 | } | 315 | } |
379 | retval = info.pos > info.offset ? info.pos - info.offset : 0; | 316 | return 0; |
380 | done: | ||
381 | return (retval); | ||
382 | } | 317 | } |