0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 #include "aic7xxx_osm.h"
0043 #include "aic7xxx_inline.h"
0044 #include "aic7xxx_93cx6.h"
0045
0046 static void ahc_dump_target_state(struct ahc_softc *ahc,
0047 struct seq_file *m,
0048 u_int our_id, char channel,
0049 u_int target_id, u_int target_offset);
0050 static void ahc_dump_device_state(struct seq_file *m,
0051 struct scsi_device *dev);
0052
0053
0054
0055
0056
0057 static const struct {
0058 u_int period_factor;
0059 u_int period;
0060 } scsi_syncrates[] = {
0061 { 0x08, 625 },
0062 { 0x09, 1250 },
0063 { 0x0a, 2500 },
0064 { 0x0b, 3030 },
0065 { 0x0c, 5000 }
0066 };
0067
0068
0069
0070
0071
0072 static u_int
0073 ahc_calc_syncsrate(u_int period_factor)
0074 {
0075 int i;
0076
0077
0078 for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) {
0079
0080 if (period_factor == scsi_syncrates[i].period_factor) {
0081
0082 return (100000000 / scsi_syncrates[i].period);
0083 }
0084 }
0085
0086
0087
0088
0089
0090 return (10000000 / (period_factor * 4 * 10));
0091 }
0092
0093 static void
0094 ahc_format_transinfo(struct seq_file *m, struct ahc_transinfo *tinfo)
0095 {
0096 u_int speed;
0097 u_int freq;
0098 u_int mb;
0099
0100 speed = 3300;
0101 freq = 0;
0102 if (tinfo->offset != 0) {
0103 freq = ahc_calc_syncsrate(tinfo->period);
0104 speed = freq;
0105 }
0106 speed *= (0x01 << tinfo->width);
0107 mb = speed / 1000;
0108 if (mb > 0)
0109 seq_printf(m, "%d.%03dMB/s transfers", mb, speed % 1000);
0110 else
0111 seq_printf(m, "%dKB/s transfers", speed);
0112
0113 if (freq != 0) {
0114 seq_printf(m, " (%d.%03dMHz%s, offset %d",
0115 freq / 1000, freq % 1000,
0116 (tinfo->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
0117 ? " DT" : "", tinfo->offset);
0118 }
0119
0120 if (tinfo->width > 0) {
0121 if (freq != 0) {
0122 seq_puts(m, ", ");
0123 } else {
0124 seq_puts(m, " (");
0125 }
0126 seq_printf(m, "%dbit)", 8 * (0x01 << tinfo->width));
0127 } else if (freq != 0) {
0128 seq_putc(m, ')');
0129 }
0130 seq_putc(m, '\n');
0131 }
0132
0133 static void
0134 ahc_dump_target_state(struct ahc_softc *ahc, struct seq_file *m,
0135 u_int our_id, char channel, u_int target_id,
0136 u_int target_offset)
0137 {
0138 struct scsi_target *starget;
0139 struct ahc_initiator_tinfo *tinfo;
0140 struct ahc_tmode_tstate *tstate;
0141 int lun;
0142
0143 tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
0144 target_id, &tstate);
0145 if ((ahc->features & AHC_TWIN) != 0)
0146 seq_printf(m, "Channel %c ", channel);
0147 seq_printf(m, "Target %d Negotiation Settings\n", target_id);
0148 seq_puts(m, "\tUser: ");
0149 ahc_format_transinfo(m, &tinfo->user);
0150 starget = ahc->platform_data->starget[target_offset];
0151 if (!starget)
0152 return;
0153
0154 seq_puts(m, "\tGoal: ");
0155 ahc_format_transinfo(m, &tinfo->goal);
0156 seq_puts(m, "\tCurr: ");
0157 ahc_format_transinfo(m, &tinfo->curr);
0158
0159 for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
0160 struct scsi_device *sdev;
0161
0162 sdev = scsi_device_lookup_by_target(starget, lun);
0163
0164 if (sdev == NULL)
0165 continue;
0166
0167 ahc_dump_device_state(m, sdev);
0168 }
0169 }
0170
0171 static void
0172 ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
0173 {
0174 struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
0175
0176 seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
0177 sdev->sdev_target->channel + 'A',
0178 sdev->sdev_target->id, (u8)sdev->lun);
0179
0180 seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
0181 seq_printf(m, "\t\tCommands Active %d\n", dev->active);
0182 seq_printf(m, "\t\tCommand Openings %d\n", dev->openings);
0183 seq_printf(m, "\t\tMax Tagged Openings %d\n", dev->maxtags);
0184 seq_printf(m, "\t\tDevice Queue Frozen Count %d\n", dev->qfrozen);
0185 }
0186
0187 int
0188 ahc_proc_write_seeprom(struct Scsi_Host *shost, char *buffer, int length)
0189 {
0190 struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
0191 struct seeprom_descriptor sd;
0192 int have_seeprom;
0193 u_long s;
0194 int paused;
0195 int written;
0196
0197
0198 written = -EINVAL;
0199 ahc_lock(ahc, &s);
0200 paused = ahc_is_paused(ahc);
0201 if (!paused)
0202 ahc_pause(ahc);
0203
0204 if (length != sizeof(struct seeprom_config)) {
0205 printk("ahc_proc_write_seeprom: incorrect buffer size\n");
0206 goto done;
0207 }
0208
0209 have_seeprom = ahc_verify_cksum((struct seeprom_config*)buffer);
0210 if (have_seeprom == 0) {
0211 printk("ahc_proc_write_seeprom: cksum verification failed\n");
0212 goto done;
0213 }
0214
0215 sd.sd_ahc = ahc;
0216 #if AHC_PCI_CONFIG > 0
0217 if ((ahc->chip & AHC_PCI) != 0) {
0218 sd.sd_control_offset = SEECTL;
0219 sd.sd_status_offset = SEECTL;
0220 sd.sd_dataout_offset = SEECTL;
0221 if (ahc->flags & AHC_LARGE_SEEPROM)
0222 sd.sd_chip = C56_66;
0223 else
0224 sd.sd_chip = C46;
0225 sd.sd_MS = SEEMS;
0226 sd.sd_RDY = SEERDY;
0227 sd.sd_CS = SEECS;
0228 sd.sd_CK = SEECK;
0229 sd.sd_DO = SEEDO;
0230 sd.sd_DI = SEEDI;
0231 have_seeprom = ahc_acquire_seeprom(ahc, &sd);
0232 } else
0233 #endif
0234 if ((ahc->chip & AHC_VL) != 0) {
0235 sd.sd_control_offset = SEECTL_2840;
0236 sd.sd_status_offset = STATUS_2840;
0237 sd.sd_dataout_offset = STATUS_2840;
0238 sd.sd_chip = C46;
0239 sd.sd_MS = 0;
0240 sd.sd_RDY = EEPROM_TF;
0241 sd.sd_CS = CS_2840;
0242 sd.sd_CK = CK_2840;
0243 sd.sd_DO = DO_2840;
0244 sd.sd_DI = DI_2840;
0245 have_seeprom = TRUE;
0246 } else {
0247 printk("ahc_proc_write_seeprom: unsupported adapter type\n");
0248 goto done;
0249 }
0250
0251 if (!have_seeprom) {
0252 printk("ahc_proc_write_seeprom: No Serial EEPROM\n");
0253 goto done;
0254 } else {
0255 u_int start_addr;
0256
0257 if (ahc->seep_config == NULL) {
0258 ahc->seep_config = kmalloc(sizeof(*ahc->seep_config),
0259 GFP_ATOMIC);
0260 if (ahc->seep_config == NULL) {
0261 printk("aic7xxx: Unable to allocate serial "
0262 "eeprom buffer. Write failing\n");
0263 goto done;
0264 }
0265 }
0266 printk("aic7xxx: Writing Serial EEPROM\n");
0267 start_addr = 32 * (ahc->channel - 'A');
0268 ahc_write_seeprom(&sd, (u_int16_t *)buffer, start_addr,
0269 sizeof(struct seeprom_config)/2);
0270 ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config,
0271 start_addr, sizeof(struct seeprom_config)/2);
0272 #if AHC_PCI_CONFIG > 0
0273 if ((ahc->chip & AHC_VL) == 0)
0274 ahc_release_seeprom(&sd);
0275 #endif
0276 written = length;
0277 }
0278
0279 done:
0280 if (!paused)
0281 ahc_unpause(ahc);
0282 ahc_unlock(ahc, &s);
0283 return (written);
0284 }
0285
0286
0287
0288
0289 int
0290 ahc_linux_show_info(struct seq_file *m, struct Scsi_Host *shost)
0291 {
0292 struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
0293 char ahc_info[256];
0294 u_int max_targ;
0295 u_int i;
0296
0297 seq_printf(m, "Adaptec AIC7xxx driver version: %s\n",
0298 AIC7XXX_DRIVER_VERSION);
0299 seq_printf(m, "%s\n", ahc->description);
0300 ahc_controller_info(ahc, ahc_info);
0301 seq_printf(m, "%s\n", ahc_info);
0302 seq_printf(m, "Allocated SCBs: %d, SG List Length: %d\n\n",
0303 ahc->scb_data->numscbs, AHC_NSEG);
0304
0305
0306 if (ahc->seep_config == NULL)
0307 seq_puts(m, "No Serial EEPROM\n");
0308 else {
0309 seq_puts(m, "Serial EEPROM:\n");
0310 for (i = 0; i < sizeof(*ahc->seep_config)/2; i++) {
0311 if (((i % 8) == 0) && (i != 0)) {
0312 seq_putc(m, '\n');
0313 }
0314 seq_printf(m, "0x%.4x ",
0315 ((uint16_t*)ahc->seep_config)[i]);
0316 }
0317 seq_putc(m, '\n');
0318 }
0319 seq_putc(m, '\n');
0320
0321 max_targ = 16;
0322 if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
0323 max_targ = 8;
0324
0325 for (i = 0; i < max_targ; i++) {
0326 u_int our_id;
0327 u_int target_id;
0328 char channel;
0329
0330 channel = 'A';
0331 our_id = ahc->our_id;
0332 target_id = i;
0333 if (i > 7 && (ahc->features & AHC_TWIN) != 0) {
0334 channel = 'B';
0335 our_id = ahc->our_id_b;
0336 target_id = i % 8;
0337 }
0338
0339 ahc_dump_target_state(ahc, m, our_id,
0340 channel, target_id, i);
0341 }
0342 return 0;
0343 }