Changeset 75


Ignore:
Timestamp:
Feb 16, 2011, 7:10:13 PM (14 years ago)
Author:
chris
Message:

atapi.c:

  • Extended workaround for incorrect direction bits to "mode sense" commands; now there's no bus lockup and subsequent port reset during boot anymore.

ahci.c:

  • Fixed timeout handling -- we use milliseconds internally while the IORB uses seconds
  • Replaced IORB completion code with a macro to improve IORB debug logging

ctxhook.c:

  • Fixed an issue which would fail to clear a port command bit if the IORB in question was not the one that caused the port engine to stop. As a result, a subsequent sanity check caused an unecessary port reset. The result was that ejecting a CD via WPS' drive object would cause the next command to fail, a reset to occur and the tray to close again right away
  • Replaced IORB completion code with a macro to improve IORB debug logging
  • added spinlocks around aws_free()

os2ahci.c

  • Replaced IORB completion code with a macro to improve IORB debug logging
  • Improved IORB debug logging to make it easier to spot the lifetime of an IORB without having to read between the lines

os2ahci.h

  • Added macro to complete an IORB including the corresponding debug log
Location:
trunk/src/os2ahci
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/ahci.c

    r74 r75  
    858858  AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb);
    859859  P_INFO *port = ai->ports + iorb_unit_port(iorb);
    860   ULONG timeout = (iorb->Timeout > 0) ? iorb->Timeout : DEFAULT_TIMEOUT;
     860  ULONG timeout = (iorb->Timeout > 0) ? iorb->Timeout * 1000 : DEFAULT_TIMEOUT;
    861861  u8 _far *port_mmio = port_base(ai, iorb_unit_port(iorb));
    862862  u16 cmd_max = ai->cmd_max;
     
    12571257    next = iorb->pNxtIORB;
    12581258    if (aws->queued_hw && (done_mask & (1UL << aws->cmd_slot))) {
    1259       /* this command has completed */
     1259      /* this hardware command has completed */
     1260      ai->ports[p].ncq_cmds &= ~(1UL << aws->cmd_slot);
     1261      ai->ports[p].reg_cmds &= ~(1UL << aws->cmd_slot);
     1262
     1263      /* call post-processing function, if any */
    12601264      if (aws->ppfunc != NULL) {
    12611265        aws->ppfunc(iorb);
     
    12681272        iorb_queue_del(&ai->ports[p].iorb_queue, iorb);
    12691273        iorb_queue_add(&done_queue, iorb);
     1274        aws_free(add_workspace(iorb));
    12701275      }
    1271 
    1272       /* clear corresponding bit in issued command bitmaps */
    1273       ai->ports[p].ncq_cmds &= ~(1UL << aws->cmd_slot);
    1274       ai->ports[p].reg_cmds &= ~(1UL << aws->cmd_slot);
    12751276    }
    12761277  }
     
    12781279  spin_unlock(drv_lock);
    12791280
    1280   /* call notification routines for all IORBs in the done queue */
     1281  /* complete all IORBs in the done queue */
    12811282  for (iorb = done_queue.root; iorb != NULL; iorb = next) {
    12821283    next = iorb->pNxtIORB;
    1283     iorb->Status = IORB_DONE;
    1284     aws_free(add_workspace(iorb));
    1285     if (iorb->RequestControl & IORB_ASYNC_POST) {
    1286       iorb->NotifyAddress(iorb);
    1287     }
     1284    complete_iorb(iorb);
    12881285  }
    12891286}
  • trunk/src/os2ahci/atapi.c

    r74 r75  
    150150  u8 cdb[ATAPI_MAX_CDB_LEN];
    151151  u16 cdb_len;
    152   int old_debug;
    153152
    154153  if (pt->ControllerCmdLen > ATAPI_MAX_CDB_LEN) {
     
    160159                (u8 _far *) cdb, (u16 _far *) &cdb_len);
    161160
    162   if (cdb[0] == 0x12) {
    163     /* Some buggy entity asks for a SCSI INQUIRY command during boot without
    164      * the flag PT_DIRECTION_IN which causes a timeout and port reset. The
    165      * easiest way around this is to hack the flag PT_DIRECTION_IN into the
    166      * request because SCSI INQUIRY commands are always device -> host.
    167      */
     161  if (cdb[0] == 0x12 || cdb[0] == 0x5a) {
     162    /* somebody sets the direction flag incorrectly for those commands */
    168163    pt->Flags |= PT_DIRECTION_IN;
    169     old_debug = debug;
    170     debug = 2;
    171164  }
    172165
     
    190183  }
    191184 
    192   if (cdb[0] == 0x12) {
    193     debug = old_debug;
    194   }
    195 
    196185  return(rc);
    197186}
  • trunk/src/os2ahci/ctxhook.c

    r74 r75  
    5555 *    given time (even if more are outstanding). This is the case for single
    5656 *    devices or port multipliers without FIS-based command switching. Error
    57  *    recovery is simple because we know which command has failed and can
    58  *    requeue all commands, replacing the failing command with a "request
    59  *    sense" command to get error details.
     57 *    recovery is simple because we know which command has failed and that
     58 *    all other commands have not yet started executing. Thus, we can requeue
     59 *    all of them, replacing the failing command with a "request sense"
     60 *    command to get error details.
    6061 *
    6162 *  - Multiple non-NCQ commands are executed on different devices behind a
     
    128129          if (aws->queued_hw) {
    129130            if (ai->ports[p].ncq_cmds & (1UL << aws->cmd_slot)) {
    130               /* NCQ commands active; force non-NCQ mode and trigger port reset */
     131              /* NCQ command; force non-NCQ mode and trigger port reset */
    131132              ai->ports[p].ncq_cmds &= ~(1UL << aws->cmd_slot);
    132133              aws->no_ncq = 1;
    133134              need_reset = 1;
    134             } else if (aws->cmd_slot == ccs) {
    135               /* this is the non-NCQ comand that failed */
     135            } else {
     136              /* regular command; clear cmd bit and identify problem IORB */
    136137              ai->ports[p].reg_cmds &= ~(1UL << aws->cmd_slot);
    137               problem_iorb = iorb;
     138              if (aws->cmd_slot == ccs) {
     139                /* this is the non-NCQ comand that failed */
     140                problem_iorb = iorb;
     141              }
    138142            }
     143            /* we can requeue all IORBs unconditionally (see function comment) */
    139144            iorb_requeue(iorb);
    140145          }
     
    184189            ADD_WORKSPACE _far *aws = add_workspace(problem_iorb);
    185190            int d = iorb_unit_device(problem_iorb);
    186             int (*req_sense)(IORBH _far *, int) =
    187               (ai->ports[p].devs[d].atapi) ? atapi_req_sense : ata_req_sense;
     191            int (*req_sense)(IORBH _far *, int) = (ai->ports[p].devs[d].atapi) ?
     192                                                  atapi_req_sense : ata_req_sense;
    188193
    189194            aws->processing = 1;
     
    214219  for (iorb = done_queue.root; iorb != NULL; iorb = next) {
    215220    next = iorb->pNxtIORB;
    216     if (iorb->RequestControl & IORB_ASYNC_POST) {
    217       iorb->NotifyAddress(iorb);
    218     }
     221
     222    spin_lock(drv_lock);
     223    aws_free(add_workspace(iorb));
     224    spin_unlock(drv_lock);
     225
     226    complete_iorb(iorb);
    219227  }
    220228
     
    355363  spin_unlock(drv_lock);
    356364
    357   /* call notification routine on all aborted IORBs */
     365  /* complete all aborted IORBs */
    358366  for (iorb = done_queue.root; iorb != NULL; iorb = next) {
    359367    next = iorb->pNxtIORB;
    360     iorb->Status = IORB_DONE | IORB_ERROR;
     368
     369    spin_lock(drv_lock);
    361370    aws_free(add_workspace(iorb));
    362     if (iorb->RequestControl & IORB_ASYNC_POST) {
    363       iorb->NotifyAddress(iorb);
    364     }
     371    spin_unlock(drv_lock);
     372
     373    iorb->Status = IORB_ERROR;
     374    complete_iorb(iorb);
    365375  }
    366376
     
    410420  }
    411421}
     422
  • trunk/src/os2ahci/os2ahci.c

    r71 r75  
    375375        /* unit handle outside of the allowed range */
    376376        dprintf("warning: IORB for %d.%d.%d out of range\n", a, p, d);
    377         iorb->Status = IORB_ERROR | IORB_DONE;
     377        iorb->Status = IORB_ERROR;
    378378        iorb->ErrorCode = IOERR_CMD_SYNTAX;
    379         if (iorb->RequestControl & IORB_ASYNC_POST) {
    380           iorb->NotifyAddress(iorb);
    381         }
     379        complete_iorb(iorb);
    382380        continue;
    383381      }
     
    964962  }
    965963
    966   ddprintf("IORB queued:  %d/%d (queue = %Fp, IORB = %Fp)\n",
    967            iorb->CommandCode, iorb->CommandModifier, queue, iorb);
     964  if (debug) {
     965    /* determine queue type (local, driver, abort or port) and minimum debug
     966     * level; otherwise, queue debug prints can become really confusing.
     967     */
     968    char *queue_type;
     969    int min_debug = 1;
     970
     971    if ((u32) queue >> 16 == (u32) (void _far *) &queue >> 16) {
     972      /* this queue is on the stack */
     973      queue_type = "local";
     974      min_debug = 2;
     975
     976    } else if (queue == &driver_queue) {
     977      queue_type = "driver";
     978
     979    } else if (queue == &abort_queue) {
     980      queue_type = "abort";
     981      min_debug = 2;
     982
     983    } else {
     984      queue_type = "port";
     985    }
     986
     987    if (debug >= min_debug) {
     988      printf("IORB %Fp queued (cmd = %d/%d, queue = %Fp [%s], timeout = %ld)\n",
     989             iorb, iorb->CommandCode, iorb->CommandModifier, queue, queue_type,
     990             iorb->Timeout);
     991    }
     992  }
    968993}
    969994
     
    9951020
    9961021  if (found) {
    997     ddprintf("IORB removed: %d/%d (queue = %Fp, IORB = %Fp) - %04x/%04x\n",
    998              iorb->CommandCode, iorb->CommandModifier, queue, iorb,
    999              iorb->Status, iorb->ErrorCode);
     1022    ddprintf("IORB %Fp removed (queue = %Fp)\n", iorb, queue);
    10001023  } else {
    10011024    dprintf("IORB %Fp not found in queue %Fp\n", iorb, queue);
     
    10491072  spin_unlock(drv_lock);
    10501073
    1051   /* notify caller, if requested */
    1052   iorb->Status |= IORB_DONE;
    1053   if (iorb->RequestControl & IORB_ASYNC_POST) {
    1054     iorb->NotifyAddress(iorb);
    1055   }
     1074  complete_iorb(iorb);
    10561075}
    10571076
  • trunk/src/os2ahci/os2ahci.def

    r71 r75  
    11library os2ahci
    2 Description '$@#thi.guten (www.thiguten.de):1.00.20110215#@OS/2 AHCI Adapter Device Driver'
     2Description '$@#thi.guten (www.thiguten.de):1.00.20110216#@OS/2 AHCI Adapter Device Driver'
    33protmode
    44
  • trunk/src/os2ahci/os2ahci.h

    r71 r75  
    201201                                  (aws)->buf = NULL;                   \
    202202                                }
     203
     204/* complete IORB */
     205#define complete_iorb(iorb)   (iorb)->Status |= IORB_DONE;                    \
     206                              dprintf("IORB %Fp complete "                    \
     207                                      "(status = 0x%04x, error = 0x%04x)\n",  \
     208                                      (iorb), (iorb)->Status,                 \
     209                                      (iorb)->ErrorCode);                     \
     210                              if ((iorb)->RequestControl & IORB_ASYNC_POST) { \
     211                                (iorb)->NotifyAddress(iorb);                  \
     212                              }
     213
    203214
    204215/******************************************************************************
  • trunk/src/os2ahci/version.h

    r74 r75  
    66
    77
    8 #define VERSION            101       /* driver version (2 implied decimals) */
     8#define VERSION            102       /* driver version (2 implied decimals) */
    99
    1010/* BLDLEVEL information (in C source modules added via macro
Note: See TracChangeset for help on using the changeset viewer.