Changeset 69 for trunk


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

Location:
trunk/src/os2ahci
Files:
8 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
  • trunk/src/os2ahci/ata.c

    r66 r69  
    107107    case AP_FEATURES:
    108108      /* ATA features word */
    109       ata_cmd.features = va_arg(va, u16);
     109      ata_cmd.features |= va_arg(va, u16);
    110110      break;
    111111
     
    118118      /* 28-bit sector address */
    119119      ata_cmd.lba_l = va_arg(va, u32);
    120       dprintf("LBA28: 0x%08lx\n", ata_cmd.lba_l);
    121120      if (ata_cmd.lba_l & 0xf0000000UL) {
    122121        dprintf("error: LBA-28 address %ld has more than 28 bits\n", ata_cmd.lba_l);
     
    133132      ata_cmd.lba_l = va_arg(va, u32);
    134133      ata_cmd.lba_h = va_arg(va, u16);
    135       dprintf("LBA48: 0x%08lx\n", ata_cmd.lba_l);
    136134      break;
    137135
     
    703701                     AP_COUNT,     (u16) (slot << 3), /* tag = slot */
    704702                     AP_SGLIST,    io->pSGList + sg_indx, (u16) sg_cnt,
    705                      AP_DEVICE,    0xc000,   /* force unit access (FUA) */
     703                     AP_DEVICE,    0x4000,
     704                     AP_DEVICE,    (io->Flags & XIO_DISABLE_HW_WRITE_CACHE) ?
     705                                   0x8000 : 0, /* force unit access */
    706706                     AP_WRITE,     1,
    707707                     AP_END);
  • trunk/src/os2ahci/atapi.c

    r68 r69  
    7575  /* translate read command to SCSI/ATAPI READ12 command.
    7676   * READ12 seems to be the most supported READ variant - according to MMC,
    77    * and its enough even for BluRay.
     77   * and it's enough even for BluRay.
    7878   */
    7979  memset(&cdb, 0x00, sizeof(cdb));
     
    167167               AP_SGLIST, pt->pSGList, pt->cSGList,
    168168               AP_WRITE, !(pt->Flags & PT_DIRECTION_IN),
    169                /* TODO: do we have to clear DMA_TO_HOST bit for
    170                 * write, mode select etc. commands?
    171                 */
    172                AP_FEATURES,  ATAPI_FEAT_DMA | ATAPI_FEAT_DMA_TO_HOST,
     169               AP_FEATURES, ATAPI_FEAT_DMA,
     170               AP_FEATURES, (pt->Flags & PT_DIRECTION_IN) ? ATAPI_FEAT_DMA_TO_HOST : 0,
    173171               AP_END);
    174172
     
    224222    iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
    225223
    226   } else {
     224  } else if (rc < 0) {
    227225    /* we failed to get info about an error -> return
    228226     * non specific device error
     
    242240  ADD_WORKSPACE _far *aws = add_workspace(iorb);
    243241  ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
     242
     243  ddphex(psd, sizeof(psd), "sense buffer:\n");
    244244
    245245  /* map sense data to some IOERR_ value */
  • trunk/src/os2ahci/ctxhook.c

    r68 r69  
    191191            if (req_sense(problem_iorb, 0) == 0) {
    192192              /* execute request sense on slot #0 before anything else comes along */
     193              ADD_StartTimerMS(&aws->timer, 5000, (PFN) timeout_callback, iorb, 0);
     194              aws->cmd_slot = 0;
    193195              ai->ports[p].reg_cmds = 1;
    194196              writel(port_mmio + PORT_CMD_ISSUE, 1);
  • trunk/src/os2ahci/init.asm

    r61 r69  
    3434                db      "OS2AHCI$"              ; name of character device
    3535                dq      0                       ; 8 reserved bytes
    36                 dd      DEV_ADAPTER_DD + DEV_INITCOMPLETE + 20h ; ADD flags
     36                dd      DEV_IOCTL2 + DEV_ADAPTER_DD + DEV_INITCOMPLETE + 20h ; ADD flags
    3737                dw      0
    3838DEVHDR          ENDS
  • trunk/src/os2ahci/os2ahci.c

    r67 r69  
    107107    break;
    108108
     109  case CMDShutdown:
     110    rc = exit_drv(((RPSAVERESTORE _far *) req)->FuncCode);
     111    break;
     112
    109113  default:
    110114    rc = STDON | STATUS_ERR_UNKCMD;
     
    284288  cprintf(exit_msg);
    285289  return(STDON | ERROR_I24_QUIET_INIT_FAIL);
     290}
     291
     292/******************************************************************************
     293 * Device driver exit handler. This handler is called when OS/2 shuts down and
     294 * flushes the write caches of all attached devices.
     295 *
     296 * NOTE: Errors are ignored because there's no way we could stop the shutdown
     297 *       or do something about the error, unless retrying endlessly is
     298 *       considered an option.
     299 */
     300USHORT exit_drv(int func)
     301{
     302  int a;
     303  int p;
     304  int d;
     305
     306  dprintf("exit_drv(%d) called\n", func);
     307
     308  if (func == 0) {
     309    /* we're only interested in the second phase of the shutdown */
     310    return(STDON);
     311  }
     312
     313  for (a = 0; a < ad_info_cnt; a++) {
     314    AD_INFO *ai = ad_infos + a;
     315
     316    for (p = 0; p <= ai->port_max; p++) {
     317      for (d = 0; d <= ai->ports[p].dev_max; d++) {
     318        if (ai->ports[p].devs[d].present) {
     319          ahci_flush_cache(ai, p, d);
     320        }
     321      }
     322    }
     323  }
     324
     325  return(STDON);
    286326}
    287327
     
    10351075
    10361076/******************************************************************************
     1077 * Timeout handler for I/O commands. Since timeout handling can involve
     1078 * lengthy operations like port resets, the main code is located in a
     1079 * separate function which is invoked via a context hook.
     1080 */
     1081void _cdecl _far timeout_callback(ULONG timer_handle, ULONG p1,
     1082                                  ULONG p2)
     1083{
     1084  IORBH _far *iorb = (IORBH _far *) p1;
     1085  int a = iorb_unit_adapter(iorb);
     1086  int p = iorb_unit_port(iorb);
     1087
     1088  ADD_CancelTimer(timer_handle);
     1089  dprintf("timeout for IORB %Fp\n", iorb);
     1090
     1091  /* Move the timed-out IORB to the abort queue. Since it's possible that the
     1092   * IORB has completed after the timeout has expired but before we got to
     1093   * this line of code, we'll check the return code of iorb_queue_del(): If it
     1094   * returns an error, the IORB must have completed a few microseconds ago and
     1095   * there is no timeout.
     1096   */
     1097  spin_lock(drv_lock);
     1098  if (iorb_queue_del(&ad_infos[a].ports[p].iorb_queue, iorb) == 0) {
     1099    iorb_queue_add(&abort_queue, iorb);
     1100    iorb->ErrorCode = IOERR_ADAPTER_TIMEOUT;
     1101  }
     1102  spin_unlock(drv_lock);
     1103
     1104  /* Trigger abort processing function. We don't really care whether this
     1105   * succeeds because the only reason why it would fail should be multiple
     1106   * calls to DevHelp_ArmCtxHook() before the context hook had a chance to
     1107   * start executing, which leaves two scenarios:
     1108   *
     1109   *  - We succeded in arming the context hook. Fine.
     1110   *
     1111   *  - We armed the context hook a second time before it had a chance to
     1112   *    start executing. In this case, the already scheduled context hook
     1113   *    will process our IORB as well.
     1114   */
     1115  DevHelp_ArmCtxHook(0, reset_ctxhook_h);
     1116}
     1117
     1118/******************************************************************************
    10371119 * small_code_ - this dummy func resolves the undefined reference linker
    10381120 * error that occurrs when linking WATCOM objects with DDK's link.exe
  • trunk/src/os2ahci/os2ahci.def

    r68 r69  
    11library os2ahci
    2 Description '$@#thi.guten (www.thiguten.de):1.00.20101227#@OS/2 AHCI Adapter Device Driver'
     2Description '$@#thi.guten (www.thiguten.de):1.00.20110107#@OS/2 AHCI Adapter Device Driver'
    33protmode
    44
  • trunk/src/os2ahci/os2ahci.h

    r68 r69  
    368368/* os2ahci.c */
    369369extern USHORT  init_drv               (RPINITIN _far *req);
     370extern USHORT  exit_drv               (int func);
    370371extern void _cdecl _far _loadds add_entry    (IORBH _far *iorb);
    371372extern void    trigger_engine         (void);
     
    385386extern void    iorb_done              (IORBH _far *iorb);
    386387extern void    iorb_requeue           (IORBH _far *iorb);
     388extern void _cdecl _far timeout_callback    (ULONG timer_handle, ULONG p1, ULONG p2);
    387389
    388390/* ahci.c */
     
    410412extern int     ahci_exec_polled_cmd         (AD_INFO *ai, int p, int d,
    411413                                             int timeout, int cmd, ...);
    412 extern int     ahci_set_dev_idle            (AD_INFO *ai, int p, int idle);
     414extern int     ahci_set_dev_idle            (AD_INFO *ai, int p, int d, int idle);
     415extern int     ahci_flush_cache             (AD_INFO *ai, int p, int d);
    413416
    414417extern int     ahci_intr                    (u16 irq);
Note: See TracChangeset for help on using the changeset viewer.