|
|
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.