Changeset 125


Ignore:
Timestamp:
Oct 8, 2011, 10:28:48 PM (14 years ago)
Author:
cjm
Message:

Version 1.21


  • Triggered by reports of performance loss with NCQ
  • New command line flag "/F" to force using write buffers even when upstream I/O requested non-buffered I/O; the primary purpose of this flag is to debug the NCQ performance drop but the flag may or may not remain.
Location:
trunk/src/os2ahci
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/Makefile

    r112 r125  
    108108apm.obj:      apm.c      Makefile $(INCS)
    109109
    110 ioctl.obj:    ioctl.c    Makefile $(INCS) atapi.h ioctl.h
     110ioctl.obj:    ioctl.c    Makefile $(INCS) ata.h atapi.h ioctl.h
    111111
    112112trace.obj:    trace.c    Makefile $(INCS)
  • trunk/src/os2ahci/ata.c

    r121 r125  
    234234   *    22 bits into 2 AHCI_SG elements.
    235235   *
    236    *  - The S/G element size for AHCI is what the spec calls "'0' based"
     236   *  - The S/G element size for AHCI is what the spec calls '0'-based
    237237   *    (i.e. 0 means 1 bytes). On top of that, the spec requires S/G transfer
    238238   *    sizes to be even in the context of 16-bit transfers, thus bit '1'
     
    248248   *    of this function will indicate how many OS/2 S/G entries were
    249249   *    successfully mapped.
    250    *
    251250   */
    252251  for (i = n = 0; i < sg_cnt; i++) {
     
    891890               AP_END);
    892891
     892  if (rc == 0) {
     893    add_workspace(iorb)->ppfunc = ata_execute_ata_pp;
     894  }
     895
    893896  return(rc);
     897}
     898
     899/******************************************************************************
     900 * Post processing function for ata_execute_ata(); the main purpose of this
     901 * function is to copy the received D2H FIS (i.e. the device registers after
     902 * command completion) back to the ATA command structure.
     903 *
     904 * See ata_cmd_to_fis() for an explanation of the mapping.
     905 */
     906void ata_execute_ata_pp(IORBH _far *iorb)
     907{
     908  AHCI_PORT_DMA _far *dma_base;
     909  ATA_CMD _far *cmd;
     910  AD_INFO *ai;
     911  u8 _far *fis;
     912  int p;
     913
     914  /* get address of D2H FIS */
     915  ai = ad_infos + iorb_unit_adapter(iorb);
     916  p = iorb_unit_port(iorb);
     917  dma_base = port_dma_base(ai, p);
     918  fis = dma_base->rx_fis + 0x40;
     919
     920  if (fis[0] != 0x34) {
     921    /* this is not a D2H FIS - give up silently */
     922    ddprintf("ata_execute_ata_pp(): D2H FIS type incorrect: %d\n", fis[0]);
     923    add_workspace(iorb)->complete = 1;
     924    return;
     925  }
     926
     927  /* map D2H FIS to the original ATA controller command structure */
     928  cmd = (ATA_CMD _far *) ((IORB_ADAPTER_PASSTHRU _far *) iorb)->pControllerCmd;
     929
     930  cmd->cmd      = fis[2];
     931  cmd->device   = fis[7];
     932  cmd->features = ((u16) fis[3])
     933                | ((u16) fis[11]);
     934  cmd->lba_l    = ((u32) fis[4])
     935                | ((u32) fis[5] << 8)
     936                | ((u32) fis[6] << 16)
     937                | ((u32) fis[8] << 24);
     938  cmd->lba_h    = ((u16) fis[9])
     939                | ((u16) fis[10] << 8);
     940  cmd->count    = ((u16) fis[12])
     941                | ((u16) fis[13] << 8);
     942
     943  dphex(cmd, sizeof(*cmd), "ahci_execute_ata_pp(): cmd after completion:\n");
     944
     945  /* signal completion to interrupt handler */
     946  add_workspace(iorb)->complete = 1;
    894947}
    895948
     
    10361089                   AP_SECTOR_48, (u32) sector, (u16) 0,
    10371090                   AP_FEATURES,  (u16) count,
    1038                    AP_COUNT,     (u16) (slot << 3), /* tag = slot */
     1091                   /* tag = slot */
     1092                   AP_COUNT,     (u16) (slot << 3),
    10391093                   AP_SGLIST,    sg_list, (u16) sg_cnt,
    10401094                   AP_DEVICE,    0x40,
    1041                    AP_DEVICE,    (write_through) ? 0x80 : 0, /* force unit access */
     1095                   /* force unit access */
     1096                   AP_DEVICE,    (write_through && !force_write_cache) ? 0x80 : 0,
    10421097                   AP_WRITE,     1,
    10431098                   AP_END);
  • trunk/src/os2ahci/ata.h

    r110 r125  
    344344
    345345/* feature values for SMART */
    346 #define ATA_SMART_ENABLE        0xD8
    347 #define ATA_SMART_READ_VALUES   0xD0
    348 #define ATA_SMART_READ_THRESHOLDS 0xD1
     346#define ATA_SMART_READ_VALUES       0xD0
     347#define ATA_SMART_READ_THRESHOLDS   0xD1
     348#define ATA_SMART_AUTOSAVE          0xD2
     349#define ATA_SMART_SAVE              0xD3
     350#define ATA_SMART_IMMEDIATE_OFFLINE 0xD4
     351#define ATA_SMART_READ_LOG          0xD5
     352#define ATA_SMART_WRITE_LOG         0xD6
     353#define ATA_SMART_ENABLE            0xD8
     354#define ATA_SMART_DISABLE           0xD9
     355#define ATA_SMART_STATUS            0xDA
     356#define ATA_SMART_AUTO_OFFLINE      0xDB
    349357
    350358/* feature values for Data Set Management */
     
    505513extern void      ata_write_pp             (IORBH _far *iorb);
    506514extern int       ata_execute_ata          (IORBH _far *iorb, int slot);
     515extern void      ata_execute_ata_pp       (IORBH _far *iorb);
    507516extern int       ata_req_sense            (IORBH _far *iorb, int slot);
    508517
  • trunk/src/os2ahci/ctxhook.c

    r121 r125  
    127127
    128128        /* get "current command slot"; only valid if there are no NCQ cmds */
    129         ccs = (int) ((readl(port_mmio + PORT_CMD) >> 8) & 0x0f);
     129        ccs = (int) ((readl(port_mmio + PORT_CMD) >> 8) & 0x1f);
    130130        ddprintf(" PORT_CMD      = 0x%x\n", ccs);
    131131
     
    145145              if (aws->cmd_slot == ccs) {
    146146                /* this is the non-NCQ command that failed */
     147                ddprintf("failing IORB: %Fp\n", iorb);
    147148                problem_iorb = iorb;
    148149              }
  • trunk/src/os2ahci/ioctl.c

    r113 r125  
    2727#include "os2ahci.h"
    2828#include "atapi.h"
     29#include "ata.h"
    2930#include "ioctl.h"
    3031
     
    4243 * we'll need to define a union to cover all IORB types in question.
    4344 */
     45#define CMDLEN sizeof(((OS2AHCI_PASSTHROUGH *) 0)->cmd)
    4446typedef struct {
    4547  IORB_ADAPTER_PASSTHRU iorb;                  /* IORB */
    4648  SCSI_STATUS_BLOCK   ssb;                     /* SCSI status block */
     49  UCHAR               cmd[CMDLEN];             /* copy of passthrough cmd
     50                                                * (need to fill ATA return
     51                                                * registers at interrupt time)
     52                                                */
    4753  UCHAR               sense[ATAPI_SENSE_LEN];  /* sense buffer */
    4854  SCATGATENTRY        sg_lst[AHCI_MAX_SG / 2]; /* scatter/gather list */
     
    5359/* -------------------------- function prototypes -------------------------- */
    5460
    55 static LIN lin(void _far *p);
     61static USHORT do_smart  (BYTE unit, BYTE sub_func, BYTE parm, void _far *buf);
     62static int    map_unit  (BYTE unit, USHORT _far *a, USHORT _far *p,
     63                         USHORT _far *d);
     64static LIN    lin       (void _far *p);
    5665
    5766IORBH _far * _far _cdecl ioctl_wakeup(IORBH _far *iorb);
     
    171180    return(STDON | STERR | ERROR_I24_BAD_UNIT);
    172181  }
    173   if ((req->buflen + 4095) / 4096 + 1 > AHCI_MAX_SG / 2) {
     182  if ((req->buflen + 4095) / 4096 + 1 > AHCI_MAX_SG / 2 ||
     183      req->cmdlen < 6 || req->cmdlen > sizeof(req->cmd)) {
    174184    return(STDON | STERR | ERROR_I24_INVALID_PARAMETER);
    175185  }
     
    206216  ic->iorb.ppSGLIST         = virt_to_phys(ic->sg_lst);
    207217
     218  memcpy(ic->cmd, req->cmd.cdb, sizeof(ic->cmd));
    208219  ic->iorb.ControllerCmdLen = req->cmdlen;
    209   ic->iorb.pControllerCmd   = req->cmd.cdb;
     220  ic->iorb.pControllerCmd   = ic->cmd;
    210221  ic->iorb.Flags            = (req->flags & PT_WRITE) ? 0 : PT_DIRECTION_IN;
    211222
     
    236247  spin_lock(drv_lock);
    237248  while (!(ic->iorb.iorbh.Status & IORB_DONE)) {
     249
    238250#   ifndef OS2AHCI_SMP
    239251      drv_lock = 0;
    240252#   endif
     253
    241254    DevHelp_ProcBlock((ULONG) (void _far *) &ic->iorb.iorbh, 30000, 1);
    242255    spin_lock(drv_lock);
     
    306319             min(ic->ssb.ReqSenseLen, req->sense_len));
    307320    }
     321
     322  } else if ((req->flags & PT_ATAPI) == 0) {
     323    /* Copy ATA cmd back to IOCTL request (ATA commands are effectively
     324     * registers which are sometimes used to indicate return conditions,
     325     * e.g. when requesting the smart status)
     326     */
     327    memcpy(&req->cmd.ata, ic->cmd, sizeof(req->cmd.ata));
    308328  }
    309329
     
    316336
    317337/******************************************************************************
     338 * Generic disk IOCTL handler; this IOCTL category has originally been defined
     339 * in IBM1S506; the code has been more or less copied from DANIS506.
     340 *
     341 * NOTE: Only a subset of the IOCTL calls are implemented in OS2AHCI at this
     342 *       point, basically those calls required to get HDMON working.
     343 */
     344USHORT ioctl_gen_dsk(RP_GENIOCTL _far *ioctl)
     345{
     346  DSKSP_CommandParameters _far *cp = (DSKSP_CommandParameters _far *) ioctl->ParmPacket;
     347  UnitInformationData _far *ui;
     348  OS2AHCI_PASSTHROUGH pt;
     349  RP_GENIOCTL tmp_ioctl;
     350  USHORT size = 0;
     351  USHORT ret;
     352  USHORT a;
     353  USHORT p;
     354  USHORT d;
     355  UCHAR unit;
     356 
     357  /* verify addressability of parm buffer (DSKSP_CommandParameters) */
     358  if (DevHelp_VerifyAccess((SEL) ((ULONG) cp >> 16),
     359                            sizeof(DSKSP_CommandParameters),
     360                            (USHORT) (ULONG) cp,
     361                            VERIFY_READONLY) != 0) {
     362    return(STDON | STERR | 0x05);
     363  }
     364  unit = cp->byPhysicalUnit;
     365
     366  /* verify addressability of data buffer (depends on function code) */
     367  switch (ioctl->Function) {
     368
     369  case DSKSP_GEN_GET_COUNTERS:
     370    size = sizeof(DeviceCountersData);
     371    break;
     372
     373  case DSKSP_GET_UNIT_INFORMATION:
     374    size = sizeof(UnitInformationData);
     375    break;
     376
     377  case DSKSP_GET_INQUIRY_DATA:
     378    size = ATA_ID_WORDS * sizeof(u16);
     379    break;
     380  }
     381
     382  if (size > 0) {
     383    if (DevHelp_VerifyAccess((SEL) ((ULONG) ioctl->DataPacket >> 16),
     384                             size, (USHORT) (ULONG) ioctl->DataPacket,
     385                             VERIFY_READWRITE) != 0) {
     386      return(STDON | STERR | 0x05);
     387    }
     388  }
     389
     390  if (map_unit(unit, &a, &p, &d)) {
     391    return(STDON | STERR | ERROR_I24_BAD_UNIT);
     392  }
     393
     394  /* execute generic disk request */
     395  switch (ioctl->Function) {
     396
     397  case DSKSP_GEN_GET_COUNTERS:
     398    /* Not supported, yet; we would need dynamically allocated device
     399     * structures to cope with the memory requirements of the corresponding
     400     * statistics buffer. For the time being, we'll return an empty buffer.
     401     */
     402    memset(ioctl->DataPacket, 0x00, sizeof(DeviceCountersData));
     403    ret = STDON;
     404    break;
     405
     406  case DSKSP_GET_UNIT_INFORMATION:
     407    /* get unit information; things like port addresses won't fit so we don't
     408     * even bother returning those.
     409     */
     410    ui = (UnitInformationData _far *) ioctl->DataPacket;
     411    memset(ui, 0x00, sizeof(*ui));
     412
     413    ui->wRevisionNumber = 1;
     414    ui->wIRQ            = ad_infos[a].irq;
     415    ui->wFlags          = UIF_VALID;
     416    ui->wFlags         |= UIF_RUNNING_BMDMA;
     417    ui->wFlags         |= (unit & 0x0001) ? UIF_SLAVE : 0;
     418    ui->wFlags         |= (ad_infos[a].ports[p].devs[d].atapi) ? UIF_ATAPI : 0;
     419    ui->wFlags         |= UIF_SATA;
     420
     421    ret = STDON;
     422    break;
     423
     424  case DSKSP_GET_INQUIRY_DATA:
     425    /* return ATA ID buffer */
     426    memset(&tmp_ioctl, 0x00, sizeof(tmp_ioctl));
     427    tmp_ioctl.Category   = OS2AHCI_IOCTL_CATEGORY;
     428    tmp_ioctl.Function   = OS2AHCI_IOCTL_PASSTHROUGH;
     429    tmp_ioctl.ParmPacket = (void _far *) &pt;
     430
     431    memset(&pt, 0x00, sizeof(pt));
     432    pt.adapter          = a;
     433    pt.port             = p;
     434    pt.device           = d;
     435    pt.cmdlen           = sizeof(pt.cmd.ata);
     436    pt.cmd.ata.cmd      = (ad_infos[a].ports[p].devs[d].atapi) ?
     437                           ATA_CMD_ID_ATAPI : ATA_CMD_ID_ATA;
     438    pt.buflen           = size;
     439    pt.buf              = lin(ioctl->DataPacket);
     440
     441    ret = gen_ioctl(&tmp_ioctl);
     442    break;
     443
     444  default:
     445    ret = STDON | STATUS_ERR_UNKCMD;
     446    break;
     447  }
     448
     449  return(ret);
     450}
     451
     452/******************************************************************************
     453 * SMART IOCTL handler; this IOCTL category has originally been defined in
     454 * IBM1S506; the code has been more or less copied from DANIS506.
     455 */
     456USHORT ioctl_smart(RP_GENIOCTL _far *ioctl)
     457{
     458  DSKSP_CommandParameters _far *cp = (DSKSP_CommandParameters _far *) ioctl->ParmPacket;
     459  USHORT size = 0;
     460  USHORT ret;
     461  UCHAR unit;
     462  UCHAR parm;
     463
     464  /* verify addressability of parm buffer (DSKSP_CommandParameters) */
     465  if (DevHelp_VerifyAccess((SEL) ((ULONG) cp >> 16),
     466                            sizeof(DSKSP_CommandParameters),
     467                            (USHORT) (ULONG) cp,
     468                            VERIFY_READONLY) != 0) {
     469    return(STDON | STERR | 0x05);
     470  }
     471  unit = cp->byPhysicalUnit;
     472
     473  /* verify addressability of data buffer (depends on SMART function) */
     474  switch (ioctl->Function) {
     475
     476  case DSKSP_SMART_GETSTATUS:
     477    size = sizeof(ULONG);
     478    break;
     479
     480  case DSKSP_SMART_GET_ATTRIBUTES:
     481  case DSKSP_SMART_GET_THRESHOLDS:
     482  case DSKSP_SMART_GET_LOG:
     483    size = 512;
     484    break;
     485  }
     486
     487  if (size > 0) {
     488    if (DevHelp_VerifyAccess((SEL) ((ULONG) ioctl->DataPacket >> 16),
     489                             size, (USHORT) (ULONG) ioctl->DataPacket,
     490                             VERIFY_READWRITE) != 0) {
     491      return(STDON | STERR | 0x05);
     492    }
     493    parm = ioctl->DataPacket[0];
     494  }
     495
     496  /* execute SMART request */
     497  switch (ioctl->Function) {
     498
     499  case DSKSP_SMART_ONOFF:
     500    ret = do_smart(unit,
     501                   (BYTE) ((parm) ? ATA_SMART_ENABLE
     502                                  : ATA_SMART_DISABLE),
     503                   0, NULL);
     504    break;
     505
     506  case DSKSP_SMART_AUTOSAVE_ONOFF:
     507    ret = do_smart(unit, ATA_SMART_AUTOSAVE,
     508                   (BYTE) ((parm) ? (BYTE) 0xf1 : 0),
     509                   NULL);
     510    break;
     511
     512  case DSKSP_SMART_AUTO_OFFLINE:
     513    ret = do_smart(unit, ATA_SMART_AUTO_OFFLINE, parm, NULL);
     514    break;
     515
     516  case DSKSP_SMART_EXEC_OFFLINE:
     517    ret = do_smart(unit, ATA_SMART_IMMEDIATE_OFFLINE, parm, NULL);
     518    break;
     519
     520  case DSKSP_SMART_SAVE:
     521    ret = do_smart(unit, ATA_SMART_SAVE, 0, NULL);
     522    break;
     523
     524  case DSKSP_SMART_GETSTATUS:
     525    ret = do_smart(unit, ATA_SMART_STATUS, 0, ioctl->DataPacket);
     526    break;
     527
     528  case DSKSP_SMART_GET_ATTRIBUTES:
     529    ret = do_smart(unit, ATA_SMART_READ_VALUES, 0, ioctl->DataPacket);
     530    break;
     531
     532  case DSKSP_SMART_GET_THRESHOLDS:
     533    ret = do_smart(unit, ATA_SMART_READ_THRESHOLDS, 0, ioctl->DataPacket);
     534    break;
     535
     536  case DSKSP_SMART_GET_LOG:
     537    ret = do_smart(unit, ATA_SMART_READ_LOG, parm, ioctl->DataPacket);
     538    break;
     539
     540  default:
     541    ret = STDON | STATUS_ERR_UNKCMD;
     542  }
     543
     544  return(ret);
     545}
     546
     547/******************************************************************************
     548 * Perform SMART request. The code has been more or less copied from DANIS506.
     549 */
     550static USHORT do_smart(BYTE unit, BYTE sub_func, BYTE parm, void _far *buf)
     551{
     552  OS2AHCI_PASSTHROUGH pt;
     553  RP_GENIOCTL ioctl;
     554  USHORT ret;
     555  USHORT a;
     556  USHORT p;
     557  USHORT d;
     558
     559  if (map_unit(unit, &a, &p, &d)) {
     560    return(STDON | STERR | ERROR_I24_BAD_UNIT);
     561  }
     562
     563  /* Perform SMART request using the existing OS2AHCI_IOTCL_PASSTHROUGH IOCTL
     564   * interface which already takes care of allocating an IORB, s/g lists, etc.
     565   */
     566  memset(&ioctl, 0x00, sizeof(ioctl));
     567  ioctl.Category   = OS2AHCI_IOCTL_CATEGORY;
     568  ioctl.Function   = OS2AHCI_IOCTL_PASSTHROUGH;
     569  ioctl.ParmPacket = (void _far *) &pt;
     570
     571  memset(&pt, 0x00, sizeof(pt));
     572  pt.adapter          = a;
     573  pt.port             = p;
     574  pt.device           = d;
     575  pt.cmdlen           = sizeof(pt.cmd.ata);
     576  pt.cmd.ata.features = sub_func;
     577  pt.cmd.ata.count    = parm;
     578  pt.cmd.ata.lba_l    = (0xc24fL << 8) | parm;
     579  pt.cmd.ata.cmd      = ATA_CMD_SMART;
     580
     581  if (buf != NULL && sub_func != ATA_SMART_STATUS) {
     582    pt.buflen         = 512;
     583    pt.buf            = lin(buf);
     584  }
     585
     586  if (((ret = gen_ioctl(&ioctl)) & STERR) == 0 &&
     587      sub_func == ATA_SMART_STATUS) {
     588
     589    /* ATA_SMART_STATUS doesn't transfer anything but instead relies on the
     590     * returned D2H FIS, mapped to the ATA CMD, to have a certain value
     591     * (0xf42c); the IOCTL result is expected to be returned as a ULONG in
     592     * the data buffer.
     593     */
     594    if (((pt.cmd.ata.lba_l >> 8) & 0xffff) == 0xf42c) {
     595      *((ULONG _far *) buf) = 1;
     596    } else {
     597      *((ULONG _far *) buf) = 0;
     598    }
     599  }
     600
     601  return(ret);
     602}
     603
     604/******************************************************************************
     605 * Map DSKSP unit number to corresponding adapter/port/device number. Units
     606 * are identified by an 8-bit adapter/device number with the lowest bit
     607 * selecting between master (0) and slave (1). This number is mapped to our
     608 * ATA/ATAPI units sequentially.
     609 */
     610static int map_unit(BYTE unit, USHORT _far *a, USHORT _far *p, USHORT _far *d)
     611{
     612  USHORT _a;
     613  USHORT _p;
     614  USHORT _d;
     615
     616  /* map unit to adapter/port/device */
     617  for (_a = 0; _a < ad_info_cnt; _a++) {
     618    AD_INFO *ai = ad_infos + _a;
     619
     620    for (_p = 0; _p <= ai->port_max; _p++) {
     621      P_INFO *pi = ai->ports + _p;
     622
     623      for (_d = 0; _d <= pi->dev_max; _d++) {
     624        if (pi->devs[_d].present) {
     625          if (--unit == 0) {
     626            /* found the device */
     627            *a = _a;
     628            *p = _p;
     629            *d = _d;
     630            return(0);
     631          }
     632        }
     633      }
     634    }
     635  }
     636
     637  /* unit not found */
     638  return(-1);
     639}
     640
     641/******************************************************************************
    318642 * Get linear address for specified virtual address.
    319643 */
  • trunk/src/os2ahci/ioctl.h

    r87 r125  
    2828
    2929/* IOCTL categories and functions */
    30 #define OS2AHCI_IOCTL_CATEGORY         0x80
     30#define OS2AHCI_IOCTL_CATEGORY         0x87
    3131#define OS2AHCI_IOCTL_GET_DEVLIST      0x01
    3232#define OS2AHCI_IOCTL_PASSTHROUGH      0x02
     33
     34/* IOCTL definitions from s506oem.h (primarily required for SMART calls) */
     35#define DSKSP_CAT_SMART             0x80  /* SMART IOCTL category */
     36#define DSKSP_SMART_ONOFF           0x20  /* turn SMART on or off */
     37#define DSKSP_SMART_AUTOSAVE_ONOFF  0x21  /* turn SMART autosave on or off */
     38#define DSKSP_SMART_SAVE            0x22  /* force save of SMART data */
     39#define DSKSP_SMART_GETSTATUS       0x23  /* get SMART status (pass/fail) */
     40#define DSKSP_SMART_GET_ATTRIBUTES  0x24  /* get SMART attributes table */
     41#define DSKSP_SMART_GET_THRESHOLDS  0x25  /* get SMART thresholds table */
     42#define DSKSP_SMART_GET_LOG         0x26  /* get SMART log        table */
     43#define DSKSP_SMART_AUTO_OFFLINE    0x27  /* set SMART offline autosave timer */
     44#define DSKSP_SMART_EXEC_OFFLINE    0x28  /* execute SMART immediate offline */
     45
     46#define SMART_CMD_ON                   1  /* on value for related SMART functions */
     47#define SMART_CMD_OFF                  0  /* off value for related SMART functions */
     48
     49#define DSKSP_CAT_GENERIC           0x90  /* generic IOCTL category */
     50#define DSKSP_GEN_GET_COUNTERS      0x40  /* get general counter values table */
     51#define DSKSP_GET_UNIT_INFORMATION  0x41  /* get unit configuration and BM DMA counters */
     52#define DSKSP_GET_INQUIRY_DATA      0x42  /* get ATA/ATAPI inquiry data */
     53
     54/* unit information structure flags from s506oem.h */
     55#define UIF_VALID           0x8000U       /* unit information valid */
     56#define UIF_TIMINGS_VALID   0x4000U       /* timing information valid */
     57#define UIF_RUNNING_BMDMA   0x2000U       /* running Bus Master DMA on unit */
     58#define UIF_RUNNING_DMA     0x1000U       /* running slave DMA on unit */
     59#define UIF_SATA            0x0004U       /* SATA             */
     60#define UIF_SLAVE           0x0002U       /* slave on channel */
     61#define UIF_ATAPI           0x0001U       /* ATAPI device if 1, ATA otherwise */
    3362
    3463/* device flags */
     
    112141} OS2AHCI_PASSTHROUGH;
    113142
     143/******************************************************************************
     144 * DSKSP command parameters; copied from s506oem.h
     145 */
     146typedef struct _DSKSP_CommandParameters
     147{
     148  BYTE        byPhysicalUnit;             /* physical unit number 0-n */
     149                                          /* 0 = Pri/Mas, 1=Pri/Sla, 2=Sec/Mas, etc. */
     150} DSKSP_CommandParameters;
     151
     152/******************************************************************************
     153 * DSKSP device counters data; copied from s506oem.h
     154 */
     155typedef struct _DeviceCountersData
     156{
     157  USHORT      wRevisionNumber;            /* counter structure revision */
     158  ULONG       TotalReadOperations;        /* total read operations performed */
     159  ULONG       TotalWriteOperations;       /* total write operations performed */
     160  ULONG       TotalWriteErrors;           /* total write errors encountered */
     161  ULONG       TotalReadErrors;            /* total read errors encountered */
     162  ULONG       TotalSeekErrors;            /* total seek errors encountered */
     163  ULONG       TotalSectorsRead;           /* total number of sectors read */
     164  ULONG       TotalSectorsWritten;        /* total number of sectors written */
     165
     166  ULONG       TotalBMReadOperations;      /* total bus master DMA read operations */
     167  ULONG       TotalBMWriteOperations;     /* total bus master DMA write operations */
     168  ULONG       ByteMisalignedBuffers;      /* total buffers on odd byte boundary */
     169  ULONG       TransfersAcross64K;         /* total buffers crossing a 64K page boundary */
     170  USHORT      TotalBMStatus;              /* total bad busmaster status */
     171  USHORT      TotalBMErrors;              /* total bad busmaster error */
     172  ULONG       TotalIRQsLost;              /* total lost interrupts */
     173  USHORT      TotalDRQsLost;              /* total lost data transfer requests */
     174  USHORT      TotalBusyErrors;            /* total device busy timeouts        */
     175  USHORT      TotalBMStatus2;             /* total bad busmaster status */
     176  USHORT      TotalChipStatus;            /* total bad chip status */
     177  USHORT      ReadErrors[4];
     178  USHORT      WriteErrors[2];
     179  USHORT      SeekErrors[2];
     180  USHORT      SATAErrors;
     181} DeviceCountersData, NEAR *NPDeviceCountersData, FAR *PDeviceCountersData;
     182
     183/******************************************************************************
     184 * DSKSP unit information data; copied from s506oem.h
     185 */
     186typedef struct _UnitInformationData
     187{
     188  USHORT      wRevisionNumber;            /* structure revision number */
     189  union {
     190    struct {
     191      USHORT  wTFBase;                    /* task file register base addr */
     192      USHORT  wDevCtl;                    /* device control register addr */
     193    } rev0;
     194    ULONG     dTFBase;                    /* task file register base addr */
     195  };
     196  USHORT      wIRQ;                       /* interrupt request level */
     197  USHORT      wFlags;                     /* flags */
     198  UCHAR       byPIO_Mode;                 /* PIO transfer mode programmed */
     199  UCHAR       byDMA_Mode;                 /* DMA transfer mode programmed */
     200  ULONG       UnitFlags1;
     201  USHORT      UnitFlags2;
     202} UnitInformationData, NEAR *NPUnitInformationData, FAR *PUnitInformationData;
     203
     204
    114205#pragma pack()
    115206
  • trunk/src/os2ahci/os2ahci.c

    r123 r125  
    7373int             thorough_scan = 1; /* if != 0, perform thorough PCI scan */
    7474int             init_reset;        /* if != 0, reset ports during init */
     75int             force_write_cache; /* if != 0, force write cache */
    7576int             verbosity = 1;     /* == 1 -> show sign on banner
    7677                                    *  > 1 -> show adapter info during boot */
     
    233234        /* reset ports during initialization */
    234235        init_reset = 1;
     236        break;
     237
     238      case 'f':
     239        /* force write cache regardless of IORB flags */
     240        force_write_cache = 1;
    235241        break;
    236242
     
    387393 * Generic IOCTL via character device driver. IOCTLs are used to control the
    388394 * driver operation and to execute native ATA and ATAPI (SCSI) commands from
    389  * ring 3 applications.
     395 * ring 3 applications. On top of that, some predefined IOCTLs (e.g. SMART
     396 * commands for ATA disks) are implemented here.
    390397 */
    391398USHORT gen_ioctl(RP_GENIOCTL _far *ioctl)
    392399{
     400  dprintf("IOCTL 0x%x/0x%x\n", (u16) ioctl->Category, (u16) ioctl->Function);
     401
    393402  switch (ioctl->Category) {
    394403
    395404  case OS2AHCI_IOCTL_CATEGORY:
    396 
    397405    switch (ioctl->Function) {
    398406
     
    404412
    405413    }
    406   }
     414
     415  case DSKSP_CAT_GENERIC:
     416    return(ioctl_gen_dsk(ioctl));
     417   
     418  case DSKSP_CAT_SMART:
     419    return(ioctl_smart(ioctl));
     420
     421  }
     422
    407423  return(STDON | STATUS_ERR_UNKCMD);
    408424}
  • trunk/src/os2ahci/os2ahci.h

    r123 r125  
    517517extern USHORT      ioctl_get_devlist  (RP_GENIOCTL _far *ioctl);
    518518extern USHORT      ioctl_passthrough  (RP_GENIOCTL _far *ioctl);
     519extern USHORT      ioctl_gen_dsk      (RP_GENIOCTL _far *ioctl);
     520extern USHORT      ioctl_smart        (RP_GENIOCTL _far *ioctl);
    519521
    520522
     
    527529extern int           thorough_scan; /* if != 0, perform thorough PCI scan */
    528530extern int           init_reset;    /* if != 0, reset ports during init */
     531extern int           force_write_cache; /* if != 0, force write cache */
    529532extern int           verbosity;     /* if != 0, show some info during boot */
    530533
  • trunk/src/os2ahci/version.h

    r121 r125  
    1414
    1515
    16 #define VERSION            119       /* driver version (2 implied decimals) */
     16#define VERSION            121       /* driver version (2 implied decimals) */
    1717
Note: See TracChangeset for help on using the changeset viewer.