1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Copyright (c) 2000-2001 Adaptec Inc. 3*1da177e4SLinus Torvalds * All rights reserved. 4*1da177e4SLinus Torvalds * 5*1da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or without 6*1da177e4SLinus Torvalds * modification, are permitted provided that the following conditions 7*1da177e4SLinus Torvalds * are met: 8*1da177e4SLinus Torvalds * 1. Redistributions of source code must retain the above copyright 9*1da177e4SLinus Torvalds * notice, this list of conditions, and the following disclaimer, 10*1da177e4SLinus Torvalds * without modification. 11*1da177e4SLinus Torvalds * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12*1da177e4SLinus Torvalds * substantially similar to the "NO WARRANTY" disclaimer below 13*1da177e4SLinus Torvalds * ("Disclaimer") and any redistribution must be conditioned upon 14*1da177e4SLinus Torvalds * including a substantially similar Disclaimer requirement for further 15*1da177e4SLinus Torvalds * binary redistribution. 16*1da177e4SLinus Torvalds * 3. Neither the names of the above-listed copyright holders nor the names 17*1da177e4SLinus Torvalds * of any contributors may be used to endorse or promote products derived 18*1da177e4SLinus Torvalds * from this software without specific prior written permission. 19*1da177e4SLinus Torvalds * 20*1da177e4SLinus Torvalds * Alternatively, this software may be distributed under the terms of the 21*1da177e4SLinus Torvalds * GNU General Public License ("GPL") version 2 as published by the Free 22*1da177e4SLinus Torvalds * Software Foundation. 23*1da177e4SLinus Torvalds * 24*1da177e4SLinus Torvalds * NO WARRANTY 25*1da177e4SLinus Torvalds * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26*1da177e4SLinus Torvalds * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27*1da177e4SLinus Torvalds * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 28*1da177e4SLinus Torvalds * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29*1da177e4SLinus Torvalds * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30*1da177e4SLinus Torvalds * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31*1da177e4SLinus Torvalds * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32*1da177e4SLinus Torvalds * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33*1da177e4SLinus Torvalds * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 34*1da177e4SLinus Torvalds * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35*1da177e4SLinus Torvalds * POSSIBILITY OF SUCH DAMAGES. 36*1da177e4SLinus Torvalds * 37*1da177e4SLinus Torvalds * String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr> 38*1da177e4SLinus Torvalds * sym driver. 39*1da177e4SLinus Torvalds * 40*1da177e4SLinus Torvalds * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#19 $ 41*1da177e4SLinus Torvalds */ 42*1da177e4SLinus Torvalds #include "aic79xx_osm.h" 43*1da177e4SLinus Torvalds #include "aic79xx_inline.h" 44*1da177e4SLinus Torvalds 45*1da177e4SLinus Torvalds static void copy_mem_info(struct info_str *info, char *data, int len); 46*1da177e4SLinus Torvalds static int copy_info(struct info_str *info, char *fmt, ...); 47*1da177e4SLinus Torvalds static void ahd_dump_target_state(struct ahd_softc *ahd, 48*1da177e4SLinus Torvalds struct info_str *info, 49*1da177e4SLinus Torvalds u_int our_id, char channel, 50*1da177e4SLinus Torvalds u_int target_id, u_int target_offset); 51*1da177e4SLinus Torvalds static void ahd_dump_device_state(struct info_str *info, 52*1da177e4SLinus Torvalds struct ahd_linux_device *dev); 53*1da177e4SLinus Torvalds static int ahd_proc_write_seeprom(struct ahd_softc *ahd, 54*1da177e4SLinus Torvalds char *buffer, int length); 55*1da177e4SLinus Torvalds 56*1da177e4SLinus Torvalds static void 57*1da177e4SLinus Torvalds copy_mem_info(struct info_str *info, char *data, int len) 58*1da177e4SLinus Torvalds { 59*1da177e4SLinus Torvalds if (info->pos + len > info->offset + info->length) 60*1da177e4SLinus Torvalds len = info->offset + info->length - info->pos; 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds if (info->pos + len < info->offset) { 63*1da177e4SLinus Torvalds info->pos += len; 64*1da177e4SLinus Torvalds return; 65*1da177e4SLinus Torvalds } 66*1da177e4SLinus Torvalds 67*1da177e4SLinus Torvalds if (info->pos < info->offset) { 68*1da177e4SLinus Torvalds off_t partial; 69*1da177e4SLinus Torvalds 70*1da177e4SLinus Torvalds partial = info->offset - info->pos; 71*1da177e4SLinus Torvalds data += partial; 72*1da177e4SLinus Torvalds info->pos += partial; 73*1da177e4SLinus Torvalds len -= partial; 74*1da177e4SLinus Torvalds } 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds if (len > 0) { 77*1da177e4SLinus Torvalds memcpy(info->buffer, data, len); 78*1da177e4SLinus Torvalds info->pos += len; 79*1da177e4SLinus Torvalds info->buffer += len; 80*1da177e4SLinus Torvalds } 81*1da177e4SLinus Torvalds } 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds static int 84*1da177e4SLinus Torvalds copy_info(struct info_str *info, char *fmt, ...) 85*1da177e4SLinus Torvalds { 86*1da177e4SLinus Torvalds va_list args; 87*1da177e4SLinus Torvalds char buf[256]; 88*1da177e4SLinus Torvalds int len; 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds va_start(args, fmt); 91*1da177e4SLinus Torvalds len = vsprintf(buf, fmt, args); 92*1da177e4SLinus Torvalds va_end(args); 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds copy_mem_info(info, buf, len); 95*1da177e4SLinus Torvalds return (len); 96*1da177e4SLinus Torvalds } 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds void 99*1da177e4SLinus Torvalds ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) 100*1da177e4SLinus Torvalds { 101*1da177e4SLinus Torvalds u_int speed; 102*1da177e4SLinus Torvalds u_int freq; 103*1da177e4SLinus Torvalds u_int mb; 104*1da177e4SLinus Torvalds 105*1da177e4SLinus Torvalds if (tinfo->period == AHD_PERIOD_UNKNOWN) { 106*1da177e4SLinus Torvalds copy_info(info, "Renegotiation Pending\n"); 107*1da177e4SLinus Torvalds return; 108*1da177e4SLinus Torvalds } 109*1da177e4SLinus Torvalds speed = 3300; 110*1da177e4SLinus Torvalds freq = 0; 111*1da177e4SLinus Torvalds if (tinfo->offset != 0) { 112*1da177e4SLinus Torvalds freq = aic_calc_syncsrate(tinfo->period); 113*1da177e4SLinus Torvalds speed = freq; 114*1da177e4SLinus Torvalds } 115*1da177e4SLinus Torvalds speed *= (0x01 << tinfo->width); 116*1da177e4SLinus Torvalds mb = speed / 1000; 117*1da177e4SLinus Torvalds if (mb > 0) 118*1da177e4SLinus Torvalds copy_info(info, "%d.%03dMB/s transfers", mb, speed % 1000); 119*1da177e4SLinus Torvalds else 120*1da177e4SLinus Torvalds copy_info(info, "%dKB/s transfers", speed); 121*1da177e4SLinus Torvalds 122*1da177e4SLinus Torvalds if (freq != 0) { 123*1da177e4SLinus Torvalds int printed_options; 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds printed_options = 0; 126*1da177e4SLinus Torvalds copy_info(info, " (%d.%03dMHz", freq / 1000, freq % 1000); 127*1da177e4SLinus Torvalds if ((tinfo->ppr_options & MSG_EXT_PPR_RD_STRM) != 0) { 128*1da177e4SLinus Torvalds copy_info(info, " RDSTRM"); 129*1da177e4SLinus Torvalds printed_options++; 130*1da177e4SLinus Torvalds } 131*1da177e4SLinus Torvalds if ((tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { 132*1da177e4SLinus Torvalds copy_info(info, "%s", printed_options ? "|DT" : " DT"); 133*1da177e4SLinus Torvalds printed_options++; 134*1da177e4SLinus Torvalds } 135*1da177e4SLinus Torvalds if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { 136*1da177e4SLinus Torvalds copy_info(info, "%s", printed_options ? "|IU" : " IU"); 137*1da177e4SLinus Torvalds printed_options++; 138*1da177e4SLinus Torvalds } 139*1da177e4SLinus Torvalds if ((tinfo->ppr_options & MSG_EXT_PPR_RTI) != 0) { 140*1da177e4SLinus Torvalds copy_info(info, "%s", 141*1da177e4SLinus Torvalds printed_options ? "|RTI" : " RTI"); 142*1da177e4SLinus Torvalds printed_options++; 143*1da177e4SLinus Torvalds } 144*1da177e4SLinus Torvalds if ((tinfo->ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) { 145*1da177e4SLinus Torvalds copy_info(info, "%s", 146*1da177e4SLinus Torvalds printed_options ? "|QAS" : " QAS"); 147*1da177e4SLinus Torvalds printed_options++; 148*1da177e4SLinus Torvalds } 149*1da177e4SLinus Torvalds } 150*1da177e4SLinus Torvalds 151*1da177e4SLinus Torvalds if (tinfo->width > 0) { 152*1da177e4SLinus Torvalds if (freq != 0) { 153*1da177e4SLinus Torvalds copy_info(info, ", "); 154*1da177e4SLinus Torvalds } else { 155*1da177e4SLinus Torvalds copy_info(info, " ("); 156*1da177e4SLinus Torvalds } 157*1da177e4SLinus Torvalds copy_info(info, "%dbit)", 8 * (0x01 << tinfo->width)); 158*1da177e4SLinus Torvalds } else if (freq != 0) { 159*1da177e4SLinus Torvalds copy_info(info, ")"); 160*1da177e4SLinus Torvalds } 161*1da177e4SLinus Torvalds copy_info(info, "\n"); 162*1da177e4SLinus Torvalds } 163*1da177e4SLinus Torvalds 164*1da177e4SLinus Torvalds static void 165*1da177e4SLinus Torvalds ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info, 166*1da177e4SLinus Torvalds u_int our_id, char channel, u_int target_id, 167*1da177e4SLinus Torvalds u_int target_offset) 168*1da177e4SLinus Torvalds { 169*1da177e4SLinus Torvalds struct ahd_linux_target *targ; 170*1da177e4SLinus Torvalds struct ahd_initiator_tinfo *tinfo; 171*1da177e4SLinus Torvalds struct ahd_tmode_tstate *tstate; 172*1da177e4SLinus Torvalds int lun; 173*1da177e4SLinus Torvalds 174*1da177e4SLinus Torvalds tinfo = ahd_fetch_transinfo(ahd, channel, our_id, 175*1da177e4SLinus Torvalds target_id, &tstate); 176*1da177e4SLinus Torvalds copy_info(info, "Target %d Negotiation Settings\n", target_id); 177*1da177e4SLinus Torvalds copy_info(info, "\tUser: "); 178*1da177e4SLinus Torvalds ahd_format_transinfo(info, &tinfo->user); 179*1da177e4SLinus Torvalds targ = ahd->platform_data->targets[target_offset]; 180*1da177e4SLinus Torvalds if (targ == NULL) 181*1da177e4SLinus Torvalds return; 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds copy_info(info, "\tGoal: "); 184*1da177e4SLinus Torvalds ahd_format_transinfo(info, &tinfo->goal); 185*1da177e4SLinus Torvalds copy_info(info, "\tCurr: "); 186*1da177e4SLinus Torvalds ahd_format_transinfo(info, &tinfo->curr); 187*1da177e4SLinus Torvalds copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected); 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds for (lun = 0; lun < AHD_NUM_LUNS; lun++) { 190*1da177e4SLinus Torvalds struct ahd_linux_device *dev; 191*1da177e4SLinus Torvalds 192*1da177e4SLinus Torvalds dev = targ->devices[lun]; 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds if (dev == NULL) 195*1da177e4SLinus Torvalds continue; 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds ahd_dump_device_state(info, dev); 198*1da177e4SLinus Torvalds } 199*1da177e4SLinus Torvalds } 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds static void 202*1da177e4SLinus Torvalds ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) 203*1da177e4SLinus Torvalds { 204*1da177e4SLinus Torvalds copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", 205*1da177e4SLinus Torvalds dev->target->channel + 'A', dev->target->target, dev->lun); 206*1da177e4SLinus Torvalds 207*1da177e4SLinus Torvalds copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); 208*1da177e4SLinus Torvalds copy_info(info, "\t\tCommands Active %d\n", dev->active); 209*1da177e4SLinus Torvalds copy_info(info, "\t\tCommand Openings %d\n", dev->openings); 210*1da177e4SLinus Torvalds copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags); 211*1da177e4SLinus Torvalds copy_info(info, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen); 212*1da177e4SLinus Torvalds } 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds static int 215*1da177e4SLinus Torvalds ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length) 216*1da177e4SLinus Torvalds { 217*1da177e4SLinus Torvalds ahd_mode_state saved_modes; 218*1da177e4SLinus Torvalds int have_seeprom; 219*1da177e4SLinus Torvalds u_long s; 220*1da177e4SLinus Torvalds int paused; 221*1da177e4SLinus Torvalds int written; 222*1da177e4SLinus Torvalds 223*1da177e4SLinus Torvalds /* Default to failure. */ 224*1da177e4SLinus Torvalds written = -EINVAL; 225*1da177e4SLinus Torvalds ahd_lock(ahd, &s); 226*1da177e4SLinus Torvalds paused = ahd_is_paused(ahd); 227*1da177e4SLinus Torvalds if (!paused) 228*1da177e4SLinus Torvalds ahd_pause(ahd); 229*1da177e4SLinus Torvalds 230*1da177e4SLinus Torvalds saved_modes = ahd_save_modes(ahd); 231*1da177e4SLinus Torvalds ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 232*1da177e4SLinus Torvalds if (length != sizeof(struct seeprom_config)) { 233*1da177e4SLinus Torvalds printf("ahd_proc_write_seeprom: incorrect buffer size\n"); 234*1da177e4SLinus Torvalds goto done; 235*1da177e4SLinus Torvalds } 236*1da177e4SLinus Torvalds 237*1da177e4SLinus Torvalds have_seeprom = ahd_verify_cksum((struct seeprom_config*)buffer); 238*1da177e4SLinus Torvalds if (have_seeprom == 0) { 239*1da177e4SLinus Torvalds printf("ahd_proc_write_seeprom: cksum verification failed\n"); 240*1da177e4SLinus Torvalds goto done; 241*1da177e4SLinus Torvalds } 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds have_seeprom = ahd_acquire_seeprom(ahd); 244*1da177e4SLinus Torvalds if (!have_seeprom) { 245*1da177e4SLinus Torvalds printf("ahd_proc_write_seeprom: No Serial EEPROM\n"); 246*1da177e4SLinus Torvalds goto done; 247*1da177e4SLinus Torvalds } else { 248*1da177e4SLinus Torvalds u_int start_addr; 249*1da177e4SLinus Torvalds 250*1da177e4SLinus Torvalds if (ahd->seep_config == NULL) { 251*1da177e4SLinus Torvalds ahd->seep_config = malloc(sizeof(*ahd->seep_config), 252*1da177e4SLinus Torvalds M_DEVBUF, M_NOWAIT); 253*1da177e4SLinus Torvalds if (ahd->seep_config == NULL) { 254*1da177e4SLinus Torvalds printf("aic79xx: Unable to allocate serial " 255*1da177e4SLinus Torvalds "eeprom buffer. Write failing\n"); 256*1da177e4SLinus Torvalds goto done; 257*1da177e4SLinus Torvalds } 258*1da177e4SLinus Torvalds } 259*1da177e4SLinus Torvalds printf("aic79xx: Writing Serial EEPROM\n"); 260*1da177e4SLinus Torvalds start_addr = 32 * (ahd->channel - 'A'); 261*1da177e4SLinus Torvalds ahd_write_seeprom(ahd, (u_int16_t *)buffer, start_addr, 262*1da177e4SLinus Torvalds sizeof(struct seeprom_config)/2); 263*1da177e4SLinus Torvalds ahd_read_seeprom(ahd, (uint16_t *)ahd->seep_config, 264*1da177e4SLinus Torvalds start_addr, sizeof(struct seeprom_config)/2, 265*1da177e4SLinus Torvalds /*ByteStream*/FALSE); 266*1da177e4SLinus Torvalds ahd_release_seeprom(ahd); 267*1da177e4SLinus Torvalds written = length; 268*1da177e4SLinus Torvalds } 269*1da177e4SLinus Torvalds 270*1da177e4SLinus Torvalds done: 271*1da177e4SLinus Torvalds ahd_restore_modes(ahd, saved_modes); 272*1da177e4SLinus Torvalds if (!paused) 273*1da177e4SLinus Torvalds ahd_unpause(ahd); 274*1da177e4SLinus Torvalds ahd_unlock(ahd, &s); 275*1da177e4SLinus Torvalds return (written); 276*1da177e4SLinus Torvalds } 277*1da177e4SLinus Torvalds /* 278*1da177e4SLinus Torvalds * Return information to handle /proc support for the driver. 279*1da177e4SLinus Torvalds */ 280*1da177e4SLinus Torvalds int 281*1da177e4SLinus Torvalds #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 282*1da177e4SLinus Torvalds ahd_linux_proc_info(char *buffer, char **start, off_t offset, 283*1da177e4SLinus Torvalds int length, int hostno, int inout) 284*1da177e4SLinus Torvalds #else 285*1da177e4SLinus Torvalds ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, 286*1da177e4SLinus Torvalds off_t offset, int length, int inout) 287*1da177e4SLinus Torvalds #endif 288*1da177e4SLinus Torvalds { 289*1da177e4SLinus Torvalds struct ahd_softc *ahd; 290*1da177e4SLinus Torvalds struct info_str info; 291*1da177e4SLinus Torvalds char ahd_info[256]; 292*1da177e4SLinus Torvalds u_long l; 293*1da177e4SLinus Torvalds u_int max_targ; 294*1da177e4SLinus Torvalds u_int i; 295*1da177e4SLinus Torvalds int retval; 296*1da177e4SLinus Torvalds 297*1da177e4SLinus Torvalds retval = -EINVAL; 298*1da177e4SLinus Torvalds ahd_list_lock(&l); 299*1da177e4SLinus Torvalds #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 300*1da177e4SLinus Torvalds TAILQ_FOREACH(ahd, &ahd_tailq, links) { 301*1da177e4SLinus Torvalds if (ahd->platform_data->host->host_no == hostno) 302*1da177e4SLinus Torvalds break; 303*1da177e4SLinus Torvalds } 304*1da177e4SLinus Torvalds #else 305*1da177e4SLinus Torvalds ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata); 306*1da177e4SLinus Torvalds #endif 307*1da177e4SLinus Torvalds 308*1da177e4SLinus Torvalds if (ahd == NULL) 309*1da177e4SLinus Torvalds goto done; 310*1da177e4SLinus Torvalds 311*1da177e4SLinus Torvalds /* Has data been written to the file? */ 312*1da177e4SLinus Torvalds if (inout == TRUE) { 313*1da177e4SLinus Torvalds retval = ahd_proc_write_seeprom(ahd, buffer, length); 314*1da177e4SLinus Torvalds goto done; 315*1da177e4SLinus Torvalds } 316*1da177e4SLinus Torvalds 317*1da177e4SLinus Torvalds if (start) 318*1da177e4SLinus Torvalds *start = buffer; 319*1da177e4SLinus Torvalds 320*1da177e4SLinus Torvalds info.buffer = buffer; 321*1da177e4SLinus Torvalds info.length = length; 322*1da177e4SLinus Torvalds info.offset = offset; 323*1da177e4SLinus Torvalds info.pos = 0; 324*1da177e4SLinus Torvalds 325*1da177e4SLinus Torvalds copy_info(&info, "Adaptec AIC79xx driver version: %s\n", 326*1da177e4SLinus Torvalds AIC79XX_DRIVER_VERSION); 327*1da177e4SLinus Torvalds copy_info(&info, "%s\n", ahd->description); 328*1da177e4SLinus Torvalds ahd_controller_info(ahd, ahd_info); 329*1da177e4SLinus Torvalds copy_info(&info, "%s\n", ahd_info); 330*1da177e4SLinus Torvalds copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n", 331*1da177e4SLinus Torvalds ahd->scb_data.numscbs, AHD_NSEG); 332*1da177e4SLinus Torvalds 333*1da177e4SLinus Torvalds max_targ = 15; 334*1da177e4SLinus Torvalds 335*1da177e4SLinus Torvalds if (ahd->seep_config == NULL) 336*1da177e4SLinus Torvalds copy_info(&info, "No Serial EEPROM\n"); 337*1da177e4SLinus Torvalds else { 338*1da177e4SLinus Torvalds copy_info(&info, "Serial EEPROM:\n"); 339*1da177e4SLinus Torvalds for (i = 0; i < sizeof(*ahd->seep_config)/2; i++) { 340*1da177e4SLinus Torvalds if (((i % 8) == 0) && (i != 0)) { 341*1da177e4SLinus Torvalds copy_info(&info, "\n"); 342*1da177e4SLinus Torvalds } 343*1da177e4SLinus Torvalds copy_info(&info, "0x%.4x ", 344*1da177e4SLinus Torvalds ((uint16_t*)ahd->seep_config)[i]); 345*1da177e4SLinus Torvalds } 346*1da177e4SLinus Torvalds copy_info(&info, "\n"); 347*1da177e4SLinus Torvalds } 348*1da177e4SLinus Torvalds copy_info(&info, "\n"); 349*1da177e4SLinus Torvalds 350*1da177e4SLinus Torvalds if ((ahd->features & AHD_WIDE) == 0) 351*1da177e4SLinus Torvalds max_targ = 7; 352*1da177e4SLinus Torvalds 353*1da177e4SLinus Torvalds for (i = 0; i <= max_targ; i++) { 354*1da177e4SLinus Torvalds 355*1da177e4SLinus Torvalds ahd_dump_target_state(ahd, &info, ahd->our_id, 'A', 356*1da177e4SLinus Torvalds /*target_id*/i, /*target_offset*/i); 357*1da177e4SLinus Torvalds } 358*1da177e4SLinus Torvalds retval = info.pos > info.offset ? info.pos - info.offset : 0; 359*1da177e4SLinus Torvalds done: 360*1da177e4SLinus Torvalds ahd_list_unlock(&l); 361*1da177e4SLinus Torvalds return (retval); 362*1da177e4SLinus Torvalds } 363