Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / scsi / aic7xxx / aic79xx_proc.c
index e01cd61..c5f0ee5 100644 (file)
@@ -47,12 +47,53 @@ static int  copy_info(struct info_str *info, char *fmt, ...);
 static void    ahd_dump_target_state(struct ahd_softc *ahd,
                                      struct info_str *info,
                                      u_int our_id, char channel,
-                                     u_int target_id, u_int target_offset);
+                                     u_int target_id);
 static void    ahd_dump_device_state(struct info_str *info,
-                                     struct ahd_linux_device *dev);
+                                     struct scsi_device *sdev);
 static int     ahd_proc_write_seeprom(struct ahd_softc *ahd,
                                       char *buffer, int length);
 
+/*
+ * Table of syncrates that don't follow the "divisible by 4"
+ * rule. This table will be expanded in future SCSI specs.
+ */
+static struct {
+       u_int period_factor;
+       u_int period;   /* in 100ths of ns */
+} scsi_syncrates[] = {
+       { 0x08, 625 },  /* FAST-160 */
+       { 0x09, 1250 }, /* FAST-80 */
+       { 0x0a, 2500 }, /* FAST-40 40MHz */
+       { 0x0b, 3030 }, /* FAST-40 33MHz */
+       { 0x0c, 5000 }  /* FAST-20 */
+};
+
+/*
+ * Return the frequency in kHz corresponding to the given
+ * sync period factor.
+ */
+static u_int
+ahd_calc_syncsrate(u_int period_factor)
+{
+       int i;
+
+       /* See if the period is in the "exception" table */
+       for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) {
+
+               if (period_factor == scsi_syncrates[i].period_factor) {
+                       /* Period in kHz */
+                       return (100000000 / scsi_syncrates[i].period);
+               }
+       }
+
+       /*
+        * Wasn't in the table, so use the standard
+        * 4 times conversion.
+        */
+       return (10000000 / (period_factor * 4 * 10));
+}
+
+
 static void
 copy_mem_info(struct info_str *info, char *data, int len)
 {
@@ -109,7 +150,7 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
         speed = 3300;
         freq = 0;
        if (tinfo->offset != 0) {
-               freq = aic_calc_syncsrate(tinfo->period);
+               freq = ahd_calc_syncsrate(tinfo->period);
                speed = freq;
        }
        speed *= (0x01 << tinfo->width);
@@ -163,10 +204,9 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
 
 static void
 ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
-                     u_int our_id, char channel, u_int target_id,
-                     u_int target_offset)
+                     u_int our_id, char channel, u_int target_id)
 {
-       struct  ahd_linux_target *targ;
+       struct  scsi_target *starget;
        struct  ahd_initiator_tinfo *tinfo;
        struct  ahd_tmode_tstate *tstate;
        int     lun;
@@ -176,20 +216,19 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
        copy_info(info, "Target %d Negotiation Settings\n", target_id);
        copy_info(info, "\tUser: ");
        ahd_format_transinfo(info, &tinfo->user);
-       targ = ahd->platform_data->targets[target_offset];
-       if (targ == NULL)
+       starget = ahd->platform_data->starget[target_id];
+       if (starget == NULL)
                return;
 
        copy_info(info, "\tGoal: ");
        ahd_format_transinfo(info, &tinfo->goal);
        copy_info(info, "\tCurr: ");
        ahd_format_transinfo(info, &tinfo->curr);
-       copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);
 
        for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
-               struct ahd_linux_device *dev;
+               struct scsi_device *dev;
 
-               dev = targ->devices[lun];
+               dev = scsi_device_lookup_by_target(starget, lun);
 
                if (dev == NULL)
                        continue;
@@ -199,10 +238,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
 }
 
 static void
-ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev)
+ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
 {
+       struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
+
        copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
-                 dev->target->channel + 'A', dev->target->target, dev->lun);
+                 sdev->sdev_target->channel + 'A',
+                 sdev->sdev_target->id, sdev->lun);
 
        copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
        copy_info(info, "\t\tCommands Active %d\n", dev->active);
@@ -278,36 +320,16 @@ done:
  * Return information to handle /proc support for the driver.
  */
 int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ahd_linux_proc_info(char *buffer, char **start, off_t offset,
-                   int length, int hostno, int inout)
-#else
 ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
                    off_t offset, int length, int inout)
-#endif
 {
-       struct  ahd_softc *ahd;
+       struct  ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
        struct  info_str info;
        char    ahd_info[256];
-       u_long  l;
        u_int   max_targ;
        u_int   i;
        int     retval;
 
-       retval = -EINVAL;
-       ahd_list_lock(&l);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-               if (ahd->platform_data->host->host_no == hostno)
-                       break;
-       }
-#else
-       ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
-#endif
-
-       if (ahd == NULL)
-               goto done;
-
         /* Has data been written to the file? */ 
        if (inout == TRUE) {
                retval = ahd_proc_write_seeprom(ahd, buffer, length);
@@ -330,7 +352,7 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
        copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
                  ahd->scb_data.numscbs, AHD_NSEG);
 
-       max_targ = 15;
+       max_targ = 16;
 
        if (ahd->seep_config == NULL)
                copy_info(&info, "No Serial EEPROM\n");
@@ -348,15 +370,14 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
        copy_info(&info, "\n");
 
        if ((ahd->features & AHD_WIDE) == 0)
-               max_targ = 7;
+               max_targ = 8;
 
-       for (i = 0; i <= max_targ; i++) {
+       for (i = 0; i < max_targ; i++) {
 
                ahd_dump_target_state(ahd, &info, ahd->our_id, 'A',
-                                     /*target_id*/i, /*target_offset*/i);
+                                     /*target_id*/i);
        }
        retval = info.pos > info.offset ? info.pos - info.offset : 0;
 done:
-       ahd_list_unlock(&l);
        return (retval);
 }