Ignore:
Timestamp:
Jan 7, 2011, 4:54:46 PM (15 years ago)
Author:
markus
Message:

fixed ATAPI packet commands; added cache flush in shutdown handler; allow write cache for NCQ commands

File:
1 edited

Legend:

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

    r68 r69  
    3838
    3939static void ahci_setup_device     (AD_INFO *ai, int p, int d, u16 *id_buf);
    40 static void _cdecl _far timeout_callback (ULONG timer_handle, ULONG p1, ULONG p2);
    4140
    4241/* ------------------------ global/static variables ------------------------ */
     
    745744  int rc;
    746745
     746  /* disable port interrupts */
     747  writel(port_mmio + PORT_IRQ_MASK, PORT_IRQ_TF_ERR);
     748
    747749  /* disable FIS reception */
    748750  if ((rc = ahci_stop_fis_rx(ai, p)) != 0) {
     
    10351037
    10361038/******************************************************************************
     1039 * Execute polled ATA/ATAPI command. This function will block until the command
     1040 * has completed or the timeout has expired, thus it should only be used during
     1041 * initialization. Furthermore, it will always use command slot zero.
     1042 *
     1043 * The difference to ahci_exec_polled_iorb() is that this function executes
     1044 * arbitrary ATA/ATAPI commands outside the context of an IORB. It's typically
     1045 * used when scanning for devices during initialization.
     1046 */
     1047int ahci_exec_polled_cmd(AD_INFO *ai, int p, int d, int timeout, int cmd, ...)
     1048{
     1049  va_list va;
     1050  u8 _far *port_mmio = port_base(ai, p);
     1051  u32 tmp;
     1052  int rc;
     1053
     1054  /* verify that command slot 0 is idle */
     1055  if (readl(port_mmio + PORT_CMD_ISSUE) & 1) {
     1056    ddprintf("port %d slot 0 is not idle; not executing polled cmd\n", p);
     1057    return(-1);
     1058  }
     1059
     1060  /* fill in command slot 0 */
     1061  va_start(va, cmd);
     1062  if ((rc = v_ata_cmd(ai, p, d, 0, cmd, va)) != 0) {
     1063    return(rc);
     1064  }
     1065
     1066  /* start command execution for slot 0 */
     1067  ddprintf("executing polled cmd...");
     1068  writel(port_mmio + PORT_CMD_ISSUE, 1);
     1069
     1070  /* wait until command has completed */
     1071  while (timeout > 0 && (readl(port_mmio + PORT_CMD_ISSUE) & 1)) {
     1072    mdelay(10);
     1073    timeout -= 10;
     1074  }
     1075  ddprintf(" done (time left = %d)\n", timeout);
     1076
     1077  /* check error condition */
     1078  if ((tmp = readl(port_mmio + PORT_SCR_ERR)) != 0) {
     1079    dprintf("SERR = 0x%08lx\n", tmp);
     1080    timeout = 0;
     1081  }
     1082  if (((tmp = readl(port_mmio + PORT_TFDATA)) & 0x89) != 0) {
     1083    dprintf("TFDATA = 0x%08lx\n", tmp);
     1084    timeout = 0;
     1085  }
     1086
     1087  if (timeout <= 0) {
     1088    ahci_reset_port(ai, p, 0);
     1089    return(-1);
     1090  }
     1091  return(0);
     1092}
     1093
     1094/******************************************************************************
     1095 * Flush write cache of the specified device. Since there's no equivalent IORB
     1096 * command, we'll execute this command directly using polling. Otherwise, we
     1097 * would have to create a fake IORB, add it to the port's IORB queue, ...
     1098 *
     1099 * Besides, this function is only called when shutting down and the code there
     1100 * would have to wait for the flush cache command to complete as well, using
     1101 * polling just the same...
     1102 */
     1103int ahci_flush_cache(AD_INFO *ai, int p, int d)
     1104{
     1105  dprintf("flushing cache on %d.%d.%d\n", ad_no(ai), p, d);
     1106  return(ahci_exec_polled_cmd(ai, p, d, 30000,
     1107                              ai->ports[p].devs[d].lba48 ? ATA_CMD_FLUSH_EXT
     1108                                                         : ATA_CMD_FLUSH,
     1109                              AP_END));
     1110}
     1111
     1112/******************************************************************************
    10371113 * set device into IDLE mode (spin down); this was used during
    10381114 * debugging/testing and is still there since it does not hurt...
     
    10401116 * is turned off.
    10411117 */
    1042 int ahci_set_dev_idle(AD_INFO *ai, int p, int idle)
     1118int ahci_set_dev_idle(AD_INFO *ai, int p, int d, int idle)
    10431119{
    10441120  ddprintf("sending IDLE=%d command to port %d\n", idle, p);
    1045   return ahci_exec_polled_cmd(ai, p, 0, 500, ATA_CMD_IDLE, AP_COUNT,
     1121  return ahci_exec_polled_cmd(ai, p, d, 500, ATA_CMD_IDLE, AP_COUNT,
    10461122                              idle ? 1 : 0, AP_END);
    1047 }
    1048 
    1049 /******************************************************************************
    1050  * Execute polled ATA/ATAPI command. This function will block until the command
    1051  * has completed or the timeout has expired, thus it should only be used during
    1052  * initialization. Furthermore, it will always use command slot zero.
    1053  *
    1054  * The difference to ahci_exec_polled_iorb() is that this function executes
    1055  * arbitrary ATA/ATAPI commands outside the context of an IORB. It's typically
    1056  * used when scanning for devices during initialization.
    1057  */
    1058 int ahci_exec_polled_cmd(AD_INFO *ai, int p, int d, int timeout, int cmd, ...)
    1059 {
    1060   va_list va;
    1061   u8 _far *port_mmio = port_base(ai, p);
    1062   u32 tmp;
    1063   int rc;
    1064 
    1065   /* verify that command slot 0 is idle */
    1066   if (readl(port_mmio + PORT_CMD_ISSUE) & 1) {
    1067     ddprintf("port %d slot 0 is not idle; not executing polled cmd\n", p);
    1068     return(-1);
    1069   }
    1070 
    1071   /* fill in command slot 0 */
    1072   va_start(va, cmd);
    1073   if ((rc = v_ata_cmd(ai, p, d, 0, cmd, va)) != 0) {
    1074     return(rc);
    1075   }
    1076 
    1077   /* start command execution for slot 0 */
    1078   ddprintf("executing polled cmd...");
    1079   writel(port_mmio + PORT_CMD_ISSUE, 1);
    1080 
    1081   /* wait until command has completed */
    1082   while (timeout > 0 && (readl(port_mmio + PORT_CMD_ISSUE) & 1)) {
    1083     mdelay(10);
    1084     timeout -= 10;
    1085   }
    1086   ddprintf(" done (time left = %d)\n", timeout);
    1087 
    1088   /* check error condition */
    1089   if ((tmp = readl(port_mmio + PORT_SCR_ERR)) != 0) {
    1090     dprintf("SERR = 0x%08lx\n", tmp);
    1091     timeout = 0;
    1092   }
    1093   if (((tmp = readl(port_mmio + PORT_TFDATA)) & 0x89) != 0) {
    1094     dprintf("TFDATA = 0x%08lx\n", tmp);
    1095     timeout = 0;
    1096   }
    1097 
    1098   if (timeout <= 0) {
    1099     ahci_reset_port(ai, p, 0);
    1100     return(-1);
    1101   }
    1102   return(0);
    11031123}
    11041124
     
    15021522    pci_hack_virtualbox();
    15031523  }
    1504 
    1505 
    1506 }
    1507 
    1508 /******************************************************************************
    1509  * Timeout handler for I/O commands. Since timeout handling can involve
    1510  * lengthy operations like port resets, the main code is located in a
    1511  * separate function which is invoked via a context hook.
    1512  */
    1513 static void _cdecl _far timeout_callback(ULONG timer_handle, ULONG p1,
    1514                                          ULONG p2)
    1515 {
    1516   IORBH _far *iorb = (IORBH _far *) p1;
    1517   int a = iorb_unit_adapter(iorb);
    1518   int p = iorb_unit_port(iorb);
    1519 
    1520   ADD_CancelTimer(timer_handle);
    1521   dprintf("timeout for IORB %Fp\n", iorb);
    1522 
    1523   /* Move the timed-out IORB to the abort queue. Since it's possible that the
    1524    * IORB has completed after the timeout has expired but before we got to
    1525    * this line of code, we'll check the return code of iorb_queue_del(): If it
    1526    * returns an error, the IORB must have completed a few microseconds ago and
    1527    * there is no timeout.
    1528    */
    1529   spin_lock(drv_lock);
    1530   if (iorb_queue_del(&ad_infos[a].ports[p].iorb_queue, iorb) == 0) {
    1531     iorb_queue_add(&abort_queue, iorb);
    1532     iorb->ErrorCode = IOERR_ADAPTER_TIMEOUT;
    1533   }
    1534   spin_unlock(drv_lock);
    1535 
    1536   /* Trigger abort processing function. We don't really care whether this
    1537    * succeeds because the only reason why it would fail should be multiple
    1538    * calls to DevHelp_ArmCtxHook() before the context hook had a chance to
    1539    * start executing, which leaves two scenarios:
    1540    *
    1541    *  - We succeded in arming the context hook. Fine.
    1542    *
    1543    *  - We armed the context hook a second time before it had a chance to
    1544    *    start executing. In this case, the already scheduled context hook
    1545    *    will process our IORB as well.
    1546    */
    1547   DevHelp_ArmCtxHook(0, reset_ctxhook_h);
    1548 }
    1549 
    1550 
     1524}
     1525
     1526
Note: See TracChangeset for help on using the changeset viewer.