|
|
1.1 root 1: /*+M*************************************************************************
2: * Adaptec AIC7xxx device driver proc support for Linux.
3: *
4: * Copyright (c) 1995, 1996 Dean W. Gehnert
5: *
6: * This program is free software; you can redistribute it and/or modify
7: * it under the terms of the GNU General Public License as published by
8: * the Free Software Foundation; either version 2, or (at your option)
9: * any later version.
10: *
11: * This program is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: * GNU General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License
17: * along with this program; see the file COPYING. If not, write to
18: * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19: *
20: * ----------------------------------------------------------------
21: * o Modified from the EATA-DMA /proc support.
22: * o Additional support for device block statistics provided by
23: * Matthew Jacob.
24: * o Correction of overflow by Heinz Mauelshagen
25: * o Adittional corrections by Doug Ledford
26: *
27: * Dean W. Gehnert, [email protected], 05/01/96
28: *
29: * $Id: aic7xxx_proc.c,v 1.1 1999/04/26 05:54:19 tb Exp $
30: *-M*************************************************************************/
31:
32: #define BLS (&aic7xxx_buffer[size])
33: #define HDRB \
34: " < 512 512-1K 1-2K 2-4K 4-8K 8-16K 16-32K 32-64K 64-128K >128K"
35:
36: #ifdef PROC_DEBUG
37: extern int vsprintf(char *, const char *, va_list);
38:
39: static void
40: proc_debug(const char *fmt, ...)
41: {
42: va_list ap;
43: char buf[256];
44:
45: va_start(ap, fmt);
46: vsprintf(buf, fmt, ap);
47: printk(buf);
48: va_end(ap);
49: }
50: #else /* PROC_DEBUG */
51: # define proc_debug(fmt, args...)
52: #endif /* PROC_DEBUG */
53:
54: static int aic7xxx_buffer_size = 0;
55: static char *aic7xxx_buffer = NULL;
56:
57:
58: /*+F*************************************************************************
59: * Function:
60: * aic7xxx_set_info
61: *
62: * Description:
63: * Set parameters for the driver from the /proc filesystem.
64: *-F*************************************************************************/
65: int
66: aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
67: {
68: proc_debug("aic7xxx_set_info(): %s\n", buffer);
69: return (-ENOSYS); /* Currently this is a no-op */
70: }
71:
72:
73: /*+F*************************************************************************
74: * Function:
75: * aic7xxx_proc_info
76: *
77: * Description:
78: * Return information to handle /proc support for the driver.
79: *-F*************************************************************************/
80: int
81: aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
82: int hostno, int inout)
83: {
84: struct Scsi_Host *HBAptr;
85: struct aic7xxx_host *p;
86: int size = 0;
87: unsigned char i;
88: struct aic7xxx_xferstats *sp;
89: unsigned char target, lun;
90:
91: HBAptr = NULL;
92:
93: for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next)
94: ;
95:
96: if (!p)
97: {
98: size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
99: if (size > length)
100: {
101: return (size);
102: }
103: else
104: {
105: return (length);
106: }
107: }
108:
109: HBAptr = p->host;
110:
111: if (inout == TRUE) /* Has data been written to the file? */
112: {
113: return (aic7xxx_set_info(buffer, length, HBAptr));
114: }
115:
116: p = (struct aic7xxx_host *) HBAptr->hostdata;
117:
118: /*
119: * It takes roughly 1K of space to hold all relevant card info, not
120: * counting any proc stats, so we start out with a 1.5k buffer size and
121: * if proc_stats is defined, then we sweep the stats structure to see
122: * how many drives we will be printing out for and add 384 bytes per
123: * device with active stats.
124: *
125: * Hmmmm...that 1.5k seems to keep growing as items get added so they
126: * can be easily viewed for debugging purposes. So, we bumped that
127: * 1.5k to 4k so we can quit having to bump it all the time.
128: */
129:
130: size = 4096;
131: for (target = 0; target < MAX_TARGETS; target++)
132: {
133: for (lun = 0; lun < MAX_LUNS; lun++)
134: {
135: if (p->stats[target][lun].xfers != 0)
136: #ifdef AIC7XXX_PROC_STATS
137: size += 512;
138: #else
139: size += 256;
140: #endif
141: }
142: }
143: if (aic7xxx_buffer_size != size)
144: {
145: if (aic7xxx_buffer != NULL)
146: {
147: kfree(aic7xxx_buffer);
148: aic7xxx_buffer_size = 0;
149: }
150: aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
151: }
152: if (aic7xxx_buffer == NULL)
153: {
154: size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
155: __LINE__);
156: return size;
157: }
158: aic7xxx_buffer_size = size;
159:
160: size = 0;
161: size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
162: size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION);
163: size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
164: size += sprintf(BLS, "\n");
165: size += sprintf(BLS, "Compile Options:\n");
166: #ifdef AIC7XXX_RESET_DELAY
167: size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY);
168: #endif
169: size += sprintf(BLS, " AIC7XXX_TAGGED_QUEUEING: Adapter Support Enabled\n");
170: size += sprintf(BLS, " Check below to see "
171: "which\n"
172: " devices use tagged "
173: "queueing\n");
174: size += sprintf(BLS, " AIC7XXX_PAGE_ENABLE : Enabled (This is no longer "
175: "an option)\n");
176: #ifdef AIC7XXX_PROC_STATS
177: size += sprintf(BLS, " AIC7XXX_PROC_STATS : Enabled\n");
178: #else
179: size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n");
180: #endif
181: size += sprintf(BLS, "\n");
182: size += sprintf(BLS, "Adapter Configuration:\n");
183: size += sprintf(BLS, " SCSI Adapter: %s\n",
184: board_names[p->board_name_index]);
185: if (p->flags & AHC_TWIN)
186: size += sprintf(BLS, " Twin Channel\n");
187: else
188: {
189: char *channel = "";
190: char *ultra = "";
191: char *wide = "Narrow ";
192: if (p->flags & AHC_MULTI_CHANNEL)
193: {
194: channel = " Channel A";
195: if (p->flags & (AHC_CHNLB|AHC_CHNLC))
196: channel = (p->flags & AHC_CHNLB) ? " Channel B" : " Channel C";
197: }
198: if (p->features & AHC_WIDE)
199: wide = "Wide ";
200: if (p->features & AHC_ULTRA2)
201: ultra = "Ultra2-LVD/SE ";
202: else if (p->features & AHC_ULTRA)
203: ultra = "Ultra ";
204: size += sprintf(BLS, " %s%sController%s\n",
205: ultra, wide, channel);
206: }
207: if( !(p->maddr) )
208: {
209: size += sprintf(BLS, " Programmed I/O Base: %lx\n", p->base);
210: }
211: else
212: {
213: size += sprintf(BLS, " PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
214: }
215: if( (p->chip & (AHC_VL | AHC_EISA)) )
216: {
217: size += sprintf(BLS, " BIOS Memory Address: 0x%08x\n", p->bios_address);
218: }
219: size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
220: (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
221: ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
222: "SEEPROM not found, using leftover BIOS values.") );
223: size += sprintf(BLS, " Adaptec SCSI BIOS: %s\n",
224: (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
225: size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
226: size += sprintf(BLS, " SCBs: Active %d, Max Active %d,\n",
227: p->activescbs, p->max_activescbs);
228: size += sprintf(BLS, " Allocated %d, HW %d, "
229: "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
230: p->scb_data->maxscbs);
231: if (p->flags & AHC_EXTERNAL_SRAM)
232: size += sprintf(BLS, " Using External SCB SRAM\n");
233: size += sprintf(BLS, " Interrupts: %ld", p->isr_count);
234: if (p->chip & AHC_EISA)
235: {
236: size += sprintf(BLS, " %s\n",
237: (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
238: }
239: else
240: {
241: size += sprintf(BLS, "\n");
242: }
243: size += sprintf(BLS, " BIOS Control Word: 0x%04x\n",
244: p->bios_control);
245: size += sprintf(BLS, " Adapter Control Word: 0x%04x\n",
246: p->adapter_control);
247: size += sprintf(BLS, " Extended Translation: %sabled\n",
248: (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
249: size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
250: if (p->features & (AHC_ULTRA | AHC_ULTRA2))
251: {
252: size += sprintf(BLS, " Ultra Enable Flags: 0x%04x\n", p->ultraenb);
253: }
254: size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable);
255: size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag);
256: #ifdef AIC7XXX_CMDS_PER_LUN
257: size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_LUN);
258: #else
259: size += sprintf(BLS, "Default Tag Queue Depth: %d\n", 8);
260: #endif
261: size += sprintf(BLS, " Tagged Queue By Device array for aic7xxx host "
262: "instance %d:\n", p->instance);
263: size += sprintf(BLS, " {");
264: for(i=0; i < (MAX_TARGETS - 1); i++)
265: size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
266: size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
267: size += sprintf(BLS, " Actual queue depth per device for aic7xxx host "
268: "instance %d:\n", p->instance);
269: size += sprintf(BLS, " {");
270: for(i=0; i < (MAX_TARGETS - 1); i++)
271: size += sprintf(BLS, "%d,", p->dev_max_queue_depth[i]);
272: size += sprintf(BLS, "%d}\n", p->dev_max_queue_depth[i]);
273:
274: size += sprintf(BLS, "\n");
275: size += sprintf(BLS, "Statistics:\n");
276: for (target = 0; target < MAX_TARGETS; target++)
277: {
278: for (lun = 0; lun < MAX_LUNS; lun++)
279: {
280: sp = &p->stats[target][lun];
281: if (sp->xfers == 0)
282: {
283: continue;
284: }
285: if (p->features & AHC_TWIN)
286: {
287: size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
288: p->host_no, (target >> 3), (target & 0x7), lun);
289: }
290: else
291: {
292: size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
293: p->host_no, 0, target, lun);
294: }
295: size += sprintf(BLS, " Device using %s/%s\n",
296: (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ?
297: "Wide" : "Narrow",
298: (p->transinfo[target].cur_offset != 0) ?
299: "Sync transfers at" : "Async transfers." );
300: if (p->transinfo[target].cur_offset != 0)
301: {
302: struct aic7xxx_syncrate *sync_rate;
303: int period = p->transinfo[target].cur_period;
304: int rate = (p->transinfo[target].cur_width ==
305: MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
306:
307: sync_rate = aic7xxx_find_syncrate(p, &period, AHC_SYNCRATE_ULTRA2);
308: if (sync_rate != NULL)
309: {
310: size += sprintf(BLS, " %s MByte/sec, offset %d\n",
311: sync_rate->rate[rate],
312: p->transinfo[target].cur_offset );
313: }
314: else
315: {
316: size += sprintf(BLS, " 3.3 MByte/sec, offset %d\n",
317: p->transinfo[target].cur_offset );
318: }
319: }
320: size += sprintf(BLS, " Device Negotiation Settings\n");
321: size += sprintf(BLS, " Period Offset Bus Width\n");
322: size += sprintf(BLS, "User %03d %03d %d\n",
323: p->transinfo[target].user_period,
324: p->transinfo[target].user_offset,
325: p->transinfo[target].user_width);
326: size += sprintf(BLS, "Goal %03d %03d %d\n",
327: p->transinfo[target].goal_period,
328: p->transinfo[target].goal_offset,
329: p->transinfo[target].goal_width);
330: size += sprintf(BLS, "Current %03d %03d %d\n",
331: p->transinfo[target].cur_period,
332: p->transinfo[target].cur_offset,
333: p->transinfo[target].cur_width);
334: size += sprintf(BLS, " Total transfers %ld (%ld read;%ld written)\n",
335: sp->xfers, sp->r_total, sp->w_total);
336: size += sprintf(BLS, " blks(512) rd=%ld; blks(512) wr=%ld\n",
337: sp->r_total512, sp->w_total512);
338: #ifdef AIC7XXX_PROC_STATS
339: size += sprintf(BLS, "%s\n", HDRB);
340: size += sprintf(BLS, " Reads:");
341: for (i = 0; i < NUMBER(sp->r_bins); i++)
342: {
343: size += sprintf(BLS, "%6ld ", sp->r_bins[i]);
344: }
345: size += sprintf(BLS, "\n");
346: size += sprintf(BLS, "Writes:");
347: for (i = 0; i < NUMBER(sp->w_bins); i++)
348: {
349: size += sprintf(BLS, "%6ld ", sp->w_bins[i]);
350: }
351: #endif /* AIC7XXX_PROC_STATS */
352: size += sprintf(BLS, "\n\n");
353: }
354: }
355:
356: if (size >= aic7xxx_buffer_size)
357: {
358: printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
359: }
360:
361: if (offset > size - 1)
362: {
363: kfree(aic7xxx_buffer);
364: aic7xxx_buffer = NULL;
365: aic7xxx_buffer_size = length = 0;
366: *start = NULL;
367: }
368: else
369: {
370: *start = &aic7xxx_buffer[offset]; /* Start of wanted data */
371: if (size - offset < length)
372: {
373: length = size - offset;
374: }
375: }
376:
377: return (length);
378: }
379:
380: /*
381: * Overrides for Emacs so that we follow Linus's tabbing style.
382: * Emacs will notice this stuff at the end of the file and automatically
383: * adjust the settings for this buffer only. This must remain at the end
384: * of the file.
385: * ---------------------------------------------------------------------------
386: * Local variables:
387: * c-indent-level: 2
388: * c-brace-imaginary-offset: 0
389: * c-brace-offset: -2
390: * c-argdecl-indent: 2
391: * c-label-offset: -2
392: * c-continued-statement-offset: 2
393: * c-continued-brace-offset: 0
394: * indent-tabs-mode: nil
395: * tab-width: 8
396: * End:
397: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.