Changeset 207


Ignore:
Timestamp:
Feb 23, 2021, 10:10:11 PM (4 years ago)
Author:
David Azarewicz
Message:

Add 64/48 bit LBA support.

Location:
trunk/src/os2ahci
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/ReadMe.txt

    r206 r207  
    1 AHCI Driver for OS/2 v2.08
     1AHCI Driver for OS/2
    22
    33Introduction
     
    7777                       use this switch.
    7878
    79 /C:<n>                 Set debug COM port base address. Values for n can be:
     79/COM:<n>               Set debug COM port base address. Values for n can be:
    8080                         1 = COM1
    8181                         2 = COM2
     
    388388Change Log
    389389==========
    390 v.2.08 01-Jan-2021 - David Azarewicz
     390v.2.08 20-Feb-2021 - David Azarewicz
    391391  Corrected RM ADD handle and unit.
    392392  Changed the internal implementation of /U to accomodate gpt filter.
     393  Added support for 48/64 bit LBA operations.
     394  Added test for non-aligned SG list element.
    393395
    394396v.2.07 19-May-2019 - David Azarewicz
  • trunk/src/os2ahci/ahci.c

    r205 r207  
    7979  u32 version;
    8080
    81   DPRINTF(2,"AHCI global registers for adapter %d %d:%d:%d irq=%d addr=0x%x\n",
     81  dprintf(0,"AHCI global registers for adapter %d %d:%d:%d irq=%d addr=0x%x\n",
    8282      ad_no(ai),
    8383      PCI_BUS_FROM_BDF(ai->bus_dev_func), PCI_DEV_FROM_BDF(ai->bus_dev_func),
    8484      PCI_FUNC_FROM_BDF(ai->bus_dev_func), ai->irq, ai->mmio_phys);
    8585
    86   for (i = 0; i <= HOST_CAP2; i += sizeof(u32)) {
     86  for (i = 0; i <= HOST_CAP2; i += sizeof(u32))
     87  {
    8788    u32 val;
    8889
     
    9899    dprintf(0," %02x: %08lx", i, val);
    99100
    100     if (i == HOST_CAP) {
     101    if (i == HOST_CAP)
     102    {
    101103      dprintf(0," -");
    102104      if (val & HOST_CAP_64)         dprintf(0," 64bit");
     
    119121      dprintf(0," cmd_slots:%d", ((val >> 8) & 0x1f) + 1);
    120122      dprintf(0," ports:%d",     (val & 0x1f) + 1);
    121     } else if (i == HOST_CTL) {
     123    }
     124    else if (i == HOST_CTL)
     125    {
    122126      dprintf(0," -");
    123127      if (val & HOST_AHCI_EN)        dprintf(0," ahci_enabled");
    124128      if (val & HOST_IRQ_EN)         dprintf(0," irq_enabled");
    125129      if (val & HOST_RESET)          dprintf(0," resetting");
    126     } else if (i == HOST_CAP2) {
     130    }
     131    else if (i == HOST_CAP2)
     132    {
    127133      dprintf(0," -");
    128134      if (val & HOST_CAP2_BOH)       dprintf(0," boh");
     
    278284  }
    279285
    280   DUMP_HOST_REGS(2,ai,1);
     286  DUMP_HOST_REGS(6,ai,1);
    281287
    282288  return(0);
     
    529535  int i;
    530536
    531   DPRINTF(1,__func__": completing initialization of adapter #%d\n", ad_no(ai));
     537  DPRINTF(2,__func__": completing initialization of adapter #%d\n", ad_no(ai));
    532538
    533539  if (!ai->int_set)
     
    609615  /* pci_enable_int(ai->bus, ai->dev_func); */
    610616
    611   DPRINTF(1,__func__": done\n");
     617  DPRINTF(2,__func__": done\n");
    612618  return(0);
    613619}
     
    834840    {
    835841      /* this port seems to have a device attached and ready for commands */
    836       DPRINTF(1,__func__": port %d seems to be attached to a device; probing...\n", p);
     842      DPRINTF(2,__func__": port %d seems to be attached to a device; probing...\n", p);
    837843
    838844      #ifdef DAZ_NEW_CODE
     
    909915  TIMER Timer;
    910916
    911   DPRINTF(2,__func__": resetting port %d.%d\n", ad_no(ai), p);
    912   DUMP_PORT_REGS(2,ai,p);
     917  DPRINTF(3,__func__": resetting port %d.%d\n", ad_no(ai), p);
     918  DUMP_PORT_REGS(3,ai,p);
    913919
    914920  /* stop port engines (we don't care whether there is an error doing so) */
     
    944950
    945951  /* wait for communication to be re-established after port reset */
    946   DPRINTF(2,"Wait for communication...\n");
     952  DPRINTF(3,"Wait for communication...\n");
    947953  TimerInit(&Timer, 500);
    948954  while (((tmp = readl(port_mmio + PORT_SCR_STAT)) & 3) != 3)
     
    950956    if (TimerCheckAndBlock(&Timer))
    951957    {
    952       DPRINTF(0,"no device present after resetting port #%d (PORT_SCR_STAT = 0x%x)\n", p, tmp);
     958      DPRINTF(2,"no device present after resetting port #%d (PORT_SCR_STAT = 0x%x)\n", p, tmp);
    953959      return(-1);
    954960    }
     
    960966
    961967  /* start port so we can receive the COMRESET FIS */
    962   DPRINTF(2,__func__": starting port %d again\n", p);
     968  DPRINTF(3,__func__": starting port %d again\n", p);
    963969  ahci_start_port(ai, p, ei);
    964970
     
    17941800  }
    17951801
    1796   dprintf(0,"port #%d interrupt error status: 0x%08lx; restarting port\n", p, irq_stat);
     1802  #ifdef DEBUG
     1803  dprintf(0,"port #%d interrupt error status: 0x%08x; restarting port\n", p, irq_stat);
     1804  #else
     1805  if (!ai->ports[p].devs[0].atapi || D32g_DbgLevel)
     1806  {
     1807    dprintf(0,"port #%d interrupt error status: 0x%08x; restarting port\n", p, irq_stat);
     1808  }
     1809  #endif
    17971810
    17981811  /* Handle device-specific errors. Those errors typically involve restarting
  • trunk/src/os2ahci/ata.c

    r205 r207  
    2626 */
    2727
     28#define INCL_LONGLONG
    2829#include "os2ahci.h"
    2930#include "ata.h"
    3031
    31 /* -------------------------- function prototypes -------------------------- */
    32 
    33 static int ata_cmd_read(IORBH *pIorb, AD_INFO *ai, int p, int d, int slot,
    34                         ULONG sector, ULONG count, SCATGATENTRY *sg_list,
    35                         ULONG sg_cnt);
    36 
    37 static int ata_cmd_write(IORBH *pIorb, AD_INFO *ai, int p, int d, int slot,
    38                          ULONG sector, ULONG count, SCATGATENTRY *sg_list,
    39                          ULONG sg_cnt, int write_through);
     32#define MAKEULL(h,l) (((ULONGLONG)h<<32)|l)
    4033
    4134/******************************************************************************
     
    256249    {
    257250      u32 chunk = (sg_size > AHCI_MAX_SG_ELEMENT_LEN) ? AHCI_MAX_SG_ELEMENT_LEN : sg_size;
     251
    258252      if (n >= AHCI_MAX_SG)
    259253      {
    260254        /* couldn't store all S/G elements in our DMA buffer */
    261         dprintf(0,"ata_cmd(): too many S/G elements\n");
     255        if (sg_size)
     256        {
     257          dprintf(0, __func__": unaligned SG element\n");
     258          return -1;
     259        }
     260        dprintf(0, __func__": too many S/G elements\n");
    262261        return(i - 1);
    263262      }
     
    341340
    342341/******************************************************************************
    343  * Get index in S/G list for the number of transferred sectors in the IORB.
    344  *
    345  * Returning io->cSGList indicates an error.
    346  *
    347  * NOTE: OS/2 makes sure S/G lists are set up such that entries at the HW
    348  *       limit will never cross sector boundaries. This means that splitting
    349  *       S/G lists into multiple commands can be done without editing the S/G
    350  *       lists.
    351  */
    352 u16 ata_get_sg_indx(IORB_EXECUTEIO *io)
    353 {
    354   ULONG offset = io->BlocksXferred * io->BlockSize;
    355   SCATGATENTRY *pSGList = (SCATGATENTRY*)Far16ToFlat(io->f16SGList);
    356   USHORT i;
    357 
    358   for (i = 0; i < io->cSGList && offset > 0; i++)
    359   {
    360     offset -= pSGList[i].XferBufLen;
    361   }
    362 
    363   return(i);
    364 }
    365 
    366 /******************************************************************************
    367342 * Get max S/G count which will fit into our HW S/G buffers. This function is
    368343 * called when the S/G list is too long and we need to split the IORB into
     
    459434 * geometry to the last full cylinder.
    460435 */
    461 int adjust_cylinders(GEOMETRY *geometry, ULONG TotalSectors)
     436int adjust_cylinders(GEOMETRY64 *geometry, ULONG TotalSectors)
    462437{
    463438  USHORT SecPerCyl;
     
    487462#define BIOS_MAX_NUMHEADS         255
    488463#define BIOS_MAX_SECTORSPERTRACK   63
    489 void log_geom_calculate_LBA_assist(GEOMETRY *geometry, ULONG TotalSectors)
     464void log_geom_calculate_LBA_assist(GEOMETRY64 *geometry, ULONG TotalSectors)
    490465{
    491466  UCHAR numSpT   = BIOS_MAX_SECTORSPERTRACK;
     
    524499  DLA_Table_Sector *pDLA = (DLA_Table_Sector*)add_workspace(pIorb)->buf;
    525500  AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb);
    526   GEOMETRY *geometry = ((IORB_GEOMETRY*)pIorb)->f16Geometry;
     501  GEOMETRY64 *geometry = (GEOMETRY64*)((IORB_GEOMETRY*)pIorb)->f16Geometry;
    527502  int p = iorb_unit_port(pIorb);
    528503  int rc;
     
    544519    geometry->NumHeads = pDLA->Heads_Per_Cylinder;
    545520    geometry->SectorsPerTrack = pDLA->Sectors_Per_Track;
    546     geometry->TotalSectors = pDLA->Cylinders * pDLA->Heads_Per_Cylinder * pDLA->Sectors_Per_Track;
     521    if (add_workspace(pIorb)->fIs64bit)
     522      geometry->ullTotalSectors = pDLA->Cylinders * pDLA->Heads_Per_Cylinder * pDLA->Sectors_Per_Track;
     523    else
     524      geometry->TotalSectors = pDLA->Cylinders * pDLA->Heads_Per_Cylinder * pDLA->Sectors_Per_Track;
    547525    return 1;
    548526  }
     
    589567void ata_get_geometry_pp(IORBH FAR16DATA *vIorb, IORBH *pIorb)
    590568{
    591   GEOMETRY *geometry = ((IORB_GEOMETRY*)pIorb)->f16Geometry;
     569  GEOMETRY64 *geometry = (GEOMETRY64*)((IORB_GEOMETRY*)pIorb)->f16Geometry;
    592570  USHORT geometry_len =  ((IORB_GEOMETRY *)pIorb)->GeometryLen;
     571  ULONGLONG ullTotalSectors;
    593572  u16 *id_buf = add_workspace(pIorb)->buf;
    594573  int a = iorb_unit_adapter(pIorb);
     
    627606   * can be unexpected and catastrophic.
    628607   */
    629   memset(geometry, 0x00, geometry_len);
     608  memset(geometry, 0, geometry_len);
    630609  geometry->BytesPerSector = ATA_SECTOR_SIZE;
    631610
     
    634613  {
    635614    /* 48-bit LBA supported */
    636     if (ATA_CAPACITY48_H(id_buf) != 0)
     615    if ((ATA_CAPACITY48_H(id_buf) != 0) && !add_workspace(pIorb)->fIs64bit)
    637616    {
    638617      /* more than 32 bits for number of sectors */
     
    640619              iorb_unit_adapter(pIorb), iorb_unit_port(pIorb),
    641620              iorb_unit_device(pIorb));
    642       geometry->TotalSectors = 0xffffffffUL;
     621      ullTotalSectors = 0xffffffff;
    643622    }
    644623    else
    645624    {
    646       geometry->TotalSectors = ATA_CAPACITY48_L(id_buf);
     625      ullTotalSectors = MAKEULL(ATA_CAPACITY48_H(id_buf), ATA_CAPACITY48_L(id_buf));
    647626    }
    648627  }
     
    650629  {
    651630    /* 28-bit LBA */
    652     geometry->TotalSectors = ATA_CAPACITY(id_buf) & 0x0fffffffUL;
     631    ullTotalSectors = ATA_CAPACITY(id_buf) & 0x0fffffff;
    653632  }
    654633
     
    663642    geometry->NumHeads        = 255;
    664643    geometry->SectorsPerTrack = track_size[a][p];
    665     geometry->TotalCylinders  = geometry->TotalSectors / ((u32) geometry->NumHeads * (u32) geometry->SectorsPerTrack);
     644    geometry->TotalCylinders  = ullTotalSectors / ((u32)geometry->NumHeads * (u32)geometry->SectorsPerTrack);
    666645    Method = "Custom";
    667646  }
     
    688667    geometry->NumHeads        = 255;
    689668    geometry->SectorsPerTrack = 63;
    690     geometry->TotalCylinders  = geometry->TotalSectors / ((u32) geometry->NumHeads * (u32) geometry->SectorsPerTrack);
     669    geometry->TotalCylinders  = ullTotalSectors / ((u32)geometry->NumHeads * (u32)geometry->SectorsPerTrack);
    691670    Method = "SCSI";
    692671  }
     
    694673  DPRINTF(2,"Physical geometry: %d cylinders, %d heads, %d sectors per track (%dMB) (%s)\n",
    695674      geometry->TotalCylinders, geometry->NumHeads, geometry->SectorsPerTrack,
    696       (geometry->TotalSectors / 2048), Method);
    697 
    698   /* Fixup the geometry in case the geometry reported by the BIOS is bad */
    699   if (adjust_cylinders(geometry, geometry->TotalSectors))
    700   { // cylinder overflow
    701     log_geom_calculate_LBA_assist(geometry, geometry->TotalSectors);
    702     geometry->TotalSectors = (USHORT)(geometry->NumHeads * geometry->SectorsPerTrack) * (ULONG)geometry->TotalCylinders;
    703   }
    704   adjust_cylinders(geometry, geometry->TotalSectors);
    705 
    706   DPRINTF(2,"Logical geometry: %d cylinders, %d heads, %d sectors per track (%dMB) (%s)\n",
    707       geometry->TotalCylinders, geometry->NumHeads, geometry->SectorsPerTrack,
    708       (geometry->TotalSectors / 2048), Method);
    709 
    710   if (is_lvm_geometry(pIorb)) Method = "LVM";
     675      (ULONG)(ullTotalSectors / 2048), Method);
     676
     677  if (is_lvm_geometry(pIorb)) Method = "LVM";  /* Writes TotalSectors/ullTotalSectors */
     678  else
     679  {
     680    if (add_workspace(pIorb)->fIs64bit)
     681    {
     682      geometry->NumHeads        = 255;
     683      geometry->SectorsPerTrack = 255;
     684      geometry->TotalCylinders  = ullTotalSectors / (255*255);
     685      geometry->ullTotalSectors = ullTotalSectors;
     686    }
     687    else
     688    {
     689      /* Fixup the geometry in case the geometry reported by the BIOS is bad */
     690      if (adjust_cylinders(geometry, ullTotalSectors))  /* Writes TotalSectors */
     691      { // cylinder overflow
     692        log_geom_calculate_LBA_assist(geometry, ullTotalSectors); /* Does not write TotalSectors */
     693        ullTotalSectors = (USHORT)(geometry->NumHeads * geometry->SectorsPerTrack) * (ULONG)geometry->TotalCylinders;
     694      }
     695      adjust_cylinders(geometry, ullTotalSectors); /* Writes TotalSectors */
     696    }
     697  }
     698  if (add_workspace(pIorb)->fIs64bit) ullTotalSectors = geometry->ullTotalSectors;
     699  else ullTotalSectors = geometry->TotalSectors;
     700
    711701  ad_infos[a].ports[p].devs[0].dev_info.Cylinders = geometry->TotalCylinders;
    712702  ad_infos[a].ports[p].devs[0].dev_info.HeadsPerCylinder = geometry->NumHeads;
    713703  ad_infos[a].ports[p].devs[0].dev_info.SectorsPerTrack = geometry->SectorsPerTrack;
    714   ad_infos[a].ports[p].devs[0].dev_info.TotalSectors = geometry->TotalSectors;
     704  ad_infos[a].ports[p].devs[0].dev_info.TotalSectors = ullTotalSectors;
    715705  ad_infos[a].ports[p].devs[0].dev_info.Method = Method;
    716706
    717   DPRINTF(2,"Reported geometry: %d cylinders, %d heads, %d sectors per track (%dMB) (%s)\n",
     707  //DAZ DPRINTF(2,"Reported geometry: %d cylinders, %d heads, %d sectors per track (%dMB) (%s)\n",
     708  DPRINTF(0,"Reported geometry: %d cylinders, %d heads, %d sectors per track (%dMB) (%s)\n",
    718709      geometry->TotalCylinders, geometry->NumHeads, geometry->SectorsPerTrack,
    719       (geometry->TotalSectors / 2048), Method);
     710      (ULONG)(ullTotalSectors / 2048), Method);
    720711
    721712  /* tell interrupt handler that this IORB is complete */
     
    737728
    738729/******************************************************************************
     730 * Fabricate ATA READ command based on the capabilities of the corresponding
     731 * device and the paramters set from above (NCQ, etc).
     732 */
     733static int ata_cmd_read(IORBH *pIorb, AD_INFO *ai, int p, int d, int slot,
     734                        ULONGLONG ullLba, ULONG count, SCATGATENTRY *sg_list,
     735                        ULONG sg_cnt)
     736{
     737  int rc;
     738
     739  if (ullLba >= (1UL << 28) || count > 256 || add_workspace(pIorb)->is_ncq)
     740  {
     741    /* need LBA48 for this command */
     742    if (!ai->ports[p].devs[d].lba48)
     743    {
     744      iorb_seterr(pIorb, IOERR_RBA_LIMIT);
     745      return(-1);
     746    }
     747    if (add_workspace(pIorb)->is_ncq)
     748    {
     749      /* use NCQ read; count goes into feature register, tag into count! */
     750      rc = ata_cmd(ai, p, d, slot, ATA_CMD_FPDMA_READ,
     751                   AP_SECTOR_48, ullLba,
     752                   AP_FEATURES,  count,
     753                   AP_COUNT,     (slot << 3), /* tag == slot */
     754                   AP_SGLIST,    sg_list, sg_cnt,
     755                   AP_DEVICE,    0x40,
     756                   AP_END);
     757    }
     758    else
     759    {
     760      rc = ata_cmd(ai, p, d, slot, ATA_CMD_READ_EXT,
     761                   AP_SECTOR_48, ullLba,
     762                   AP_COUNT,     count,
     763                   AP_SGLIST,    sg_list, sg_cnt,
     764                   AP_DEVICE,    0x40,
     765                   AP_END);
     766    }
     767
     768  }
     769  else
     770  {
     771    rc = ata_cmd(ai, p, d, slot, ATA_CMD_READ,
     772                 AP_SECTOR_28, (ULONG)ullLba,
     773                 AP_COUNT,     count & 0xffU,
     774                 AP_SGLIST,    sg_list, sg_cnt,
     775                 AP_DEVICE,    0x40,
     776                 AP_END);
     777  }
     778
     779  return(rc);
     780}
     781
     782/******************************************************************************
    739783 * Read sectors from AHCI device.
    740784 */
     
    744788  SCATGATENTRY *pSGList = (SCATGATENTRY*)Far16ToFlat(io->f16SGList);
    745789  AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb);
    746   ULONG sector = io->RBA + io->BlocksXferred;
     790  ULONGLONG ullLba = io->RBA + io->BlocksXferred;
    747791  USHORT count = io->BlockCount - io->BlocksXferred;
    748792  USHORT sg_indx;
     
    762806    /* unaligned S/G addresses present; need to use double buffers */
    763807    return(ata_read_unaligned(pIorb, slot));
     808  }
     809
     810  if (add_workspace(pIorb)->fIs64bit)
     811  {
     812    ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA + io->BlocksXferred;
    764813  }
    765814
     
    778827  do
    779828  {
    780     sg_indx = ata_get_sg_indx(io);
     829    sg_indx = SgIndexFromOffset(pSGList, io->cSGList, io->BlocksXferred * io->BlockSize);
    781830    sg_cnt = io->cSGList - sg_indx;
    782     if ((rc = ata_cmd_read(pIorb, ai, p, d, slot, sector, count,
    783                            pSGList + sg_indx, sg_cnt)) > 0)
     831    rc = ata_cmd_read(pIorb, ai, p, d, slot, ullLba, count, pSGList + sg_indx, sg_cnt);
     832    if (rc > 0)
    784833    {
    785834      /* couldn't map all S/G elements */
     
    802851    add_workspace(pIorb)->unaligned = 1;
    803852    return(ata_read_unaligned(pIorb, slot));
    804 
    805853  }
    806854  else
     
    823871  ADD_WORKSPACE *aws = add_workspace(pIorb);
    824872  AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb);
    825   ULONG sector = io->RBA + io->BlocksXferred;
     873  ULONGLONG ullLba = io->RBA + io->BlocksXferred;
    826874  SCATGATENTRY sg_single;
    827875  int p = iorb_unit_port(pIorb);
     
    829877  int rc;
    830878
    831   DPRINTF(7,"ata_read_unaligned(%d.%d.%d, %d)\n", ad_no(ai), p, d, sector);
     879  if (add_workspace(pIorb)->fIs64bit)
     880  {
     881    ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA + io->BlocksXferred;
     882  }
     883
     884  DPRINTF(7,"ata_read_unaligned(%d.%d.%d, %lld)\n", ad_no(ai), p, d, ullLba);
    832885  ai->ports[p].unaligned_read_count++;
    833886
     
    842895  sg_single.ppXferBuf = MemPhysAdr(aws->buf);
    843896  sg_single.XferBufLen = io->BlockSize;
    844   rc = ata_cmd_read(pIorb, ai, p, d, slot, sector, 1, &sg_single, 1);
     897  rc = ata_cmd_read(pIorb, ai, p, d, slot, ullLba, 1, &sg_single, 1);
    845898
    846899  if (rc == 0) {
     
    873926  {
    874927    /* copy transfer buffer to corresponding physical address in S/G list */
    875     sg_memcpy(pSGList, io->cSGList,
    876               (ULONG) io->BlocksXferred * (ULONG) io->BlockSize,
    877               aws->buf, io->BlockSize, BUF_TO_SG);
     928    CopySgBuf(pSGList, io->cSGList, (ULONG)io->BlocksXferred * (ULONG)io->BlockSize,
     929              aws->buf, io->BlockSize, BUF_TO_SGL);
    878930  }
    879931
     
    902954  int p = iorb_unit_port(pIorb);
    903955  int d = iorb_unit_device(pIorb);
     956  ULONGLONG ullLba = io->RBA;
    904957  int rc;
    905958
     
    910963  }
    911964
     965  if (add_workspace(pIorb)->fIs64bit)
     966  {
     967    ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA;
     968  }
     969
    912970  /* prepare verify command */
    913   if (io->RBA >= (1UL << 28) || io->BlockCount > 256)
     971  if (ullLba >= (1UL << 28) || io->BlockCount > 256)
    914972  {
    915973    /* need LBA48 for this command */
     
    919977    }
    920978    rc = ata_cmd(ai, p, d, slot, ATA_CMD_VERIFY_EXT,
    921                  AP_SECTOR_48, io->RBA, 0,
     979                 AP_SECTOR_48, ullLba,
    922980                 AP_COUNT,     io->BlockCount,
    923981                 AP_DEVICE,    0x40,
     
    925983  } else {
    926984    rc = ata_cmd(ai, p, d, slot, ATA_CMD_VERIFY,
    927                  AP_SECTOR_28, io->RBA,
     985                 AP_SECTOR_28, (ULONG)ullLba,
    928986                 AP_COUNT,     io->BlockCount & 0xffU,
    929987                 AP_DEVICE,    0x40,
     
    935993
    936994/******************************************************************************
     995 * Fabricate ATA WRITE command based on the capabilities of the corresponding
     996 * device and the paramters set from above (NCQ, etc)
     997 */
     998static int ata_cmd_write(IORBH *pIorb, AD_INFO *ai, int p, int d, int slot,
     999                         ULONGLONG ullLba, ULONG count, SCATGATENTRY *sg_list,
     1000                         ULONG sg_cnt, int write_through)
     1001{
     1002  int rc;
     1003
     1004  if (ullLba >= (1UL << 28) || count > 256 || add_workspace(pIorb)->is_ncq)
     1005  {
     1006    /* need LBA48 for this command */
     1007    if (!ai->ports[p].devs[d].lba48)
     1008    {
     1009      iorb_seterr(pIorb, IOERR_RBA_LIMIT);
     1010      return(-1);
     1011    }
     1012    if (add_workspace(pIorb)->is_ncq)
     1013    {
     1014      /* use NCQ write; count goes into feature register, tag into count! */
     1015      rc = ata_cmd(ai, p, d, slot, ATA_CMD_FPDMA_WRITE,
     1016                   AP_SECTOR_48, ullLba,
     1017                   AP_FEATURES,  count,
     1018                   /* tag = slot */
     1019                   AP_COUNT,     (slot << 3),
     1020                   AP_SGLIST,    sg_list, sg_cnt,
     1021                   AP_DEVICE,    0x40,
     1022                   /* force unit access */
     1023                   AP_DEVICE,    (write_through && !force_write_cache) ? 0x80 : 0,
     1024                   AP_WRITE,     1,
     1025                   AP_END);
     1026    }
     1027    else
     1028    {
     1029      rc = ata_cmd(ai, p, d, slot, ATA_CMD_WRITE_EXT,
     1030                   AP_SECTOR_48, ullLba,
     1031                   AP_COUNT,     count,
     1032                   AP_SGLIST,    sg_list, sg_cnt,
     1033                   AP_DEVICE,    0x40,
     1034                   AP_WRITE,     1,
     1035                   AP_END);
     1036    }
     1037  }
     1038  else
     1039  {
     1040    rc = ata_cmd(ai, p, d, slot, ATA_CMD_WRITE,
     1041                 AP_SECTOR_28, (ULONG)ullLba,
     1042                 AP_COUNT,     count & 0xffU,
     1043                 AP_SGLIST,    sg_list, sg_cnt,
     1044                 AP_DEVICE,    0x40,
     1045                 AP_WRITE,     1,
     1046                 AP_END);
     1047  }
     1048
     1049  return(rc);
     1050}
     1051
     1052/******************************************************************************
    9371053 * Write sectors to AHCI device.
    9381054 */
     
    9421058  SCATGATENTRY *pSGList = (SCATGATENTRY*)Far16ToFlat(io->f16SGList);
    9431059  AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb);
    944   ULONG sector = io->RBA + io->BlocksXferred;
     1060  ULONGLONG ullLba = io->RBA + io->BlocksXferred;
    9451061  USHORT count = io->BlockCount - io->BlocksXferred;
    9461062  USHORT sg_indx;
     
    9621078  }
    9631079
     1080  if (add_workspace(pIorb)->fIs64bit)
     1081  {
     1082    ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA + io->BlocksXferred;
     1083  }
     1084
    9641085  /* prepare write command while keeping an eye on S/G count limitations */
    9651086  do {
    966     sg_indx = ata_get_sg_indx(io);
     1087    sg_indx = SgIndexFromOffset(pSGList, io->cSGList, io->BlocksXferred * io->BlockSize);
    9671088    sg_cnt = io->cSGList - sg_indx;
    968     if ((rc = ata_cmd_write(pIorb, ai, p, d, slot, sector, count,
     1089    if ((rc = ata_cmd_write(pIorb, ai, p, d, slot, ullLba, count,
    9691090                            pSGList + sg_indx, sg_cnt,
    9701091                            io->Flags & XIO_DISABLE_HW_WRITE_CACHE)) > 0)
    9711092    {
    9721093      /* couldn't map all S/G elements */
    973       ata_max_sg_cnt(io, sg_indx, (USHORT) rc, &sg_cnt, &count);
     1094      ata_max_sg_cnt(io, sg_indx, (USHORT)rc, &sg_cnt, &count);
    9741095    }
    9751096  } while (rc > 0 && sg_cnt > 0);
     
    10101131  ADD_WORKSPACE *aws = add_workspace(pIorb);
    10111132  AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb);
    1012   ULONG sector = io->RBA + io->BlocksXferred;
     1133  ULONGLONG ullLba = io->RBA + io->BlocksXferred;
    10131134  SCATGATENTRY sg_single;
    10141135  int p = iorb_unit_port(pIorb);
     
    10161137  int rc;
    10171138
    1018   DPRINTF(7,"ata_write_unaligned(%d.%d.%d, %d)\n", ad_no(ai), p, d, sector);
     1139  if (add_workspace(pIorb)->fIs64bit)
     1140  {
     1141    ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA + io->BlocksXferred;
     1142  }
     1143
     1144  DPRINTF(7,"ata_write_unaligned(%d.%d.%d, %lld)\n", ad_no(ai), p, d, ullLba);
    10191145
    10201146  /* allocate transfer buffer */
     
    10261152
    10271153  /* copy next sector from S/G list to transfer buffer */
    1028   sg_memcpy(pSGList, io->cSGList,
    1029             (ULONG) io->BlocksXferred * (ULONG) io->BlockSize,
    1030             aws->buf, io->BlockSize, SG_TO_BUF);
     1154  CopySgBuf(pSGList, io->cSGList, (ULONG)io->BlocksXferred * (ULONG)io->BlockSize,
     1155            aws->buf, io->BlockSize, SGL_TO_BUF);
    10311156
    10321157  /* prepare write command using transfer buffer */
    10331158  sg_single.ppXferBuf = MemPhysAdr(aws->buf);
    10341159  sg_single.XferBufLen = io->BlockSize;
    1035   rc = ata_cmd_write(pIorb, ai, p, d, slot, sector, 1, &sg_single, 1,
     1160  rc = ata_cmd_write(pIorb, ai, p, d, slot, ullLba, 1, &sg_single, 1,
    10361161                     io->Flags & XIO_DISABLE_HW_WRITE_CACHE);
    10371162
     
    12501375
    12511376/******************************************************************************
    1252  * Fabricate ATA READ command based on the capabilities of the corresponding
    1253  * device and the paramters set from above (NCQ, etc).
    1254  */
    1255 static int ata_cmd_read(IORBH *pIorb, AD_INFO *ai, int p, int d, int slot,
    1256                         ULONG sector, ULONG count, SCATGATENTRY *sg_list,
    1257                         ULONG sg_cnt)
    1258 {
    1259   int rc;
    1260 
    1261   if (sector >= (1UL << 28) || count > 256 || add_workspace(pIorb)->is_ncq)
    1262   {
    1263     /* need LBA48 for this command */
    1264     if (!ai->ports[p].devs[d].lba48)
    1265     {
    1266       iorb_seterr(pIorb, IOERR_RBA_LIMIT);
    1267       return(-1);
    1268     }
    1269     if (add_workspace(pIorb)->is_ncq)
    1270     {
    1271       /* use NCQ read; count goes into feature register, tag into count! */
    1272       rc = ata_cmd(ai, p, d, slot, ATA_CMD_FPDMA_READ,
    1273                    AP_SECTOR_48, sector, 0,
    1274                    AP_FEATURES,  count,
    1275                    AP_COUNT,     (slot << 3), /* tag == slot */
    1276                    AP_SGLIST,    sg_list, sg_cnt,
    1277                    AP_DEVICE,    0x40,
    1278                    AP_END);
    1279     }
    1280     else
    1281     {
    1282       rc = ata_cmd(ai, p, d, slot, ATA_CMD_READ_EXT,
    1283                    AP_SECTOR_48, sector, 0,
    1284                    AP_COUNT,     count,
    1285                    AP_SGLIST,    sg_list, sg_cnt,
    1286                    AP_DEVICE,    0x40,
    1287                    AP_END);
    1288     }
    1289 
    1290   }
    1291   else
    1292   {
    1293     rc = ata_cmd(ai, p, d, slot, ATA_CMD_READ,
    1294                  AP_SECTOR_28, sector,
    1295                  AP_COUNT,     count & 0xffU,
    1296                  AP_SGLIST,    sg_list, sg_cnt,
    1297                  AP_DEVICE,    0x40,
    1298                  AP_END);
    1299   }
    1300 
    1301   return(rc);
    1302 }
    1303 
    1304 /******************************************************************************
    1305  * Fabricate ATA WRITE command based on the capabilities of the corresponding
    1306  * device and the paramters set from above (NCQ, etc)
    1307  */
    1308 static int ata_cmd_write(IORBH *pIorb, AD_INFO *ai, int p, int d, int slot,
    1309                          ULONG sector, ULONG count, SCATGATENTRY *sg_list,
    1310                          ULONG sg_cnt, int write_through)
    1311 {
    1312   int rc;
    1313 
    1314   if (sector >= (1UL << 28) || count > 256 || add_workspace(pIorb)->is_ncq)
    1315   {
    1316     /* need LBA48 for this command */
    1317     if (!ai->ports[p].devs[d].lba48)
    1318     {
    1319       iorb_seterr(pIorb, IOERR_RBA_LIMIT);
    1320       return(-1);
    1321     }
    1322     if (add_workspace(pIorb)->is_ncq)
    1323     {
    1324       /* use NCQ write; count goes into feature register, tag into count! */
    1325       rc = ata_cmd(ai, p, d, slot, ATA_CMD_FPDMA_WRITE,
    1326                    AP_SECTOR_48, sector, 0,
    1327                    AP_FEATURES,  count,
    1328                    /* tag = slot */
    1329                    AP_COUNT,     (slot << 3),
    1330                    AP_SGLIST,    sg_list, sg_cnt,
    1331                    AP_DEVICE,    0x40,
    1332                    /* force unit access */
    1333                    AP_DEVICE,    (write_through && !force_write_cache) ? 0x80 : 0,
    1334                    AP_WRITE,     1,
    1335                    AP_END);
    1336     }
    1337     else
    1338     {
    1339       rc = ata_cmd(ai, p, d, slot, ATA_CMD_WRITE_EXT,
    1340                    AP_SECTOR_48, sector, 0,
    1341                    AP_COUNT,     count,
    1342                    AP_SGLIST,    sg_list, sg_cnt,
    1343                    AP_DEVICE,    0x40,
    1344                    AP_WRITE,     1,
    1345                    AP_END);
    1346     }
    1347   }
    1348   else
    1349   {
    1350     rc = ata_cmd(ai, p, d, slot, ATA_CMD_WRITE,
    1351                  AP_SECTOR_28, sector,
    1352                  AP_COUNT,     count & 0xffU,
    1353                  AP_SGLIST,    sg_list, sg_cnt,
    1354                  AP_DEVICE,    0x40,
    1355                  AP_WRITE,     1,
    1356                  AP_END);
    1357   }
    1358 
    1359   return(rc);
    1360 }
    1361 
    1362 /******************************************************************************
    1363  * Copy block from S/G list to virtual address or vice versa.
    1364  */
    1365 void sg_memcpy(SCATGATENTRY *sg_list, USHORT sg_cnt, ULONG sg_off,
    1366                void *buf, USHORT len, SG_MEMCPY_DIRECTION dir)
    1367 {
    1368   USHORT i;
    1369   USHORT l;
    1370   ULONG phys_addr;
    1371   ULONG pos = 0;
    1372   char *p;
    1373 
    1374   /* walk through S/G list to find the elements involved in the operation */
    1375   for (i = 0; i < sg_cnt && len > 0; i++)
    1376   {
    1377     if (pos <= sg_off && pos + sg_list[i].XferBufLen > sg_off)
    1378     {
    1379       /* this S/G element intersects with the block to be copied */
    1380       phys_addr = sg_list[i].ppXferBuf + (sg_off - pos);
    1381       if ((l = sg_list[i].XferBufLen - (sg_off - pos)) > len)
    1382       {
    1383         l = len;
    1384       }
    1385 
    1386       if (Dev32Help_PhysToLin(phys_addr, l, (PVOID) &p))
    1387       {
    1388         panic(__func__": DevHelp_PhysToLin() failed");
    1389       }
    1390       if (dir == SG_TO_BUF)
    1391       {
    1392         memcpy(buf, p, l);
    1393       }
    1394       else
    1395       {
    1396         memcpy(p, buf, l);
    1397       }
    1398       sg_off += l;
    1399       buf = (char *) buf + l;
    1400       len -= l;
    1401     }
    1402 
    1403     pos += sg_list[i].XferBufLen;
    1404   }
    1405 }
    1406 
    1407 /******************************************************************************
    14081377 * Halt processing by submitting an internal error. This is a last resort and
    14091378 * should only be called when the system state is corrupt.
  • trunk/src/os2ahci/ata.h

    r205 r207  
    492492extern int v_ata_cmd(AD_INFO *ai, int port, int device, int slot, int cmd, va_list va);
    493493extern void ata_cmd_to_fis(u8 *fis, ATA_CMD *cmd, int device);
    494 extern USHORT ata_get_sg_indx(IORB_EXECUTEIO *io);
    495494extern void ata_max_sg_cnt(IORB_EXECUTEIO *io, USHORT sg_indx, USHORT sg_max, USHORT *sg_cnt, USHORT *sector_cnt);
    496 
    497495extern int ata_get_geometry(IORBH FAR16DATA *iorb, IORBH *pIorb, int slot);
    498496extern void ata_get_geometry_pp(IORBH FAR16DATA *vIorb, IORBH *pIorb);
     
    508506extern void ata_execute_ata_pp(IORBH FAR16DATA *vIorb, IORBH *pIorb);
    509507extern int ata_req_sense(IORBH FAR16DATA *vIorb, IORBH *pIorb, int slot);
    510 
    511508extern char *ata_dev_name(u16 *id_buf);
    512509
  • trunk/src/os2ahci/atapi.c

    r205 r207  
    9999
    100100    /* update S/G count and index */
    101     sg_indx = ata_get_sg_indx(io);
     101    sg_indx = SgIndexFromOffset(pSGList, io->cSGList, io->BlocksXferred * io->BlockSize);
    102102    sg_cnt = io->cSGList - sg_indx;
    103103
  • trunk/src/os2ahci/os2ahci.c

    r206 r207  
    8989int suspended;
    9090int resume_sleep_flag;
     91AHCISTATS AhciStats;
    9192
    9293/* apapter/port-specific options saved when parsing the command line */
     
    189190  UtSetDriverName("OS2AHCI$");
    190191  Header.ulCaps |= DEV_ADAPTER_DD; /* DAZ This flag is not really needed. */
     192  memset(&AhciStats, 0, sizeof(AhciStats));
     193  AhciStats.ulSize = sizeof(AhciStats);
     194  AhciStats.ulVersion = 0x101;
    191195
    192196  /* create driver-level spinlock */
     
    219223    }
    220224
    221     if (ArgCmp(pszCmdLine, "C:"))
    222     {
    223       pszCmdLine += 2;
     225    if (ArgCmp(pszCmdLine, "COM:"))
     226    {
     227      pszCmdLine += 4;
    224228      /* set COM port base address for debug messages */
    225229      D32g_ComBase = strtol(pszCmdLine, &pszCmdLine, 0);
     
    483487{
    484488  DPRINTF(2,"IOCTL 0x%x/0x%x\n", ioctl->ioctl.bCategory, ioctl->ioctl.bFunction);
     489  AhciStats.ulTestCount2++;
    485490
    486491  switch (ioctl->ioctl.bCategory)
     
    803808    break;
    804809
     810  case IOCC_GEOMETRY_64:
     811    add_workspace(pIorb)->fIs64bit = 1;
     812    /* fall thru */
    805813  case IOCC_GEOMETRY:
    806814    iocc_geometry(vIorb, pIorb);
    807815    break;
    808816
     817  case IOCC_EXECUTE_IO_64:
     818    add_workspace(pIorb)->fIs64bit = 1;
     819    /* fall thru */
    809820  case IOCC_EXECUTE_IO:
    810821    iocc_execute_io(vIorb, pIorb);
     
    816827
    817828  case IOCC_ADAPTER_PASSTHRU:
     829    AhciStats.ulTestCount1++;
    818830    iocc_adapter_passthru(vIorb, pIorb);
    819831    break;
     
    12151227
    12161228  case IOCM_WRITE:
    1217     add_workspace(pIorb)->idempotent = 1;
    1218     ahci_write(vIorb, pIorb);
    1219     break;
    1220 
    12211229  case IOCM_WRITE_VERIFY:
    12221230    add_workspace(pIorb)->idempotent = 1;
  • trunk/src/os2ahci/os2ahci.h

    r205 r207  
    230230
    231231typedef struct {
    232     USHORT Cylinders;
     232    ULONG Cylinders;
    233233    USHORT HeadsPerCylinder;
    234234    USHORT SectorsPerTrack;
    235     ULONG  TotalSectors;
     235    ULONGLONG  TotalSectors;
    236236    char *Method;
    237237} DEV_INFO;
     
    248248  u32           dma_buf_phys;          /* 14 physical address of DMA scratch buffer */
    249249  u8           *dma_buf;               /* 18 DMA scatch buffers */
     250  u32 unaligned_read_count;
     251  u32 error_count;
     252  u32 ulResetCount; /* added in 2.07 */
    250253
    251254  struct {                             /* 1c */
     
    263266    char dev_name[AHCI_DEV_NAME_LEN];
    264267  } devs[AHCI_MAX_DEVS];
    265 
    266   u32 unaligned_read_count;
    267   u32 error_count;
    268   u32 ulResetCount; /* added in 2.07 */
    269268} P_INFO;
    270269
     
    313312  unsigned short processing    :1;     /* 0e IORB is being processd */
    314313  unsigned short idempotent    :1;     /*    IORB is idempotent (can be retried) */
     314  unsigned short fIs64bit      :1;     /* Transaction is a 64 bit operation */
    315315  unsigned short queued_hw     :1;     /*    IORB has been queued to hardware */
    316316  unsigned short no_ncq        :1;     /*    must not use native command queuing */
     
    354354                                   /* These are the four entries which correspond to the entries in the partition table. */
    355355} DLA_Table_Sector, *PDLA_Table_Sector;
     356
     357typedef struct _ahcistats_
     358{
     359  ULONG ulSize;
     360  ULONG ulVersion;
     361  ULONG ulTestCount3;
     362  ULONG ulTestCount2;
     363  ULONG ulTestCount1;
     364} AHCISTATS;
    356365
    357366static inline unsigned long readl(void *a)
     
    487496extern int suspended; /* indicates if the driver is suspended */
    488497extern int resume_sleep_flag;
     498extern AHCISTATS AhciStats;
    489499
    490500/* port restart context hook and input data */
  • trunk/src/os2ahci/trace.c

    r205 r207  
    55 */
    66
     7#define INCL_LONGLONG
    78#include "os2ahci.h"
    89
     
    3738        if (pi->devs[d].present)
    3839        {
    39           if (iFlag) dprintf(0,"  Port %d:\n", p);
     40          if (iFlag) dprintf(0,"  Port %d:", p);
    4041          iFlag = 0;
    41           dprintf(0,"    Drive %d:", d);
    4242          if (pi->devs[d].atapi) dprintf(0," atapi");
    4343          if (pi->devs[d].removable) dprintf(0," removable");
     
    4646            dprintf(0," %d cylinders, %d heads, %d sectors per track (%dMB) (%s)",
    4747              pi->devs[d].dev_info.Cylinders, pi->devs[d].dev_info.HeadsPerCylinder, pi->devs[d].dev_info.SectorsPerTrack,
    48               pi->devs[d].dev_info.TotalSectors/2048, pi->devs[d].dev_info.Method);
     48              (ULONG)(pi->devs[d].dev_info.TotalSectors/2048), pi->devs[d].dev_info.Method);
    4949          }
    50           if (pi->devs[d].ignored) dprintf(0," Not a usable disk");
     50          if (pi->devs[d].ignored) dprintf(0," Unusable");
    5151          dprintf(0,"\n");
    52           dprintf(0,"             Model: %s\n", pi->devs[d].dev_name);
     52          dprintf(0,"          Model: %s\n", pi->devs[d].dev_name);
    5353        }
    5454        else if (verbosity > 0)
    5555        {
    56           if (iFlag) dprintf(0,"  Port %d:\n", p);
    57           iFlag = 0;
    58           dprintf(0,"    No drive present\n");
     56          if (iFlag) dprintf(0,"  Port %d: No drive present\n", p);
    5957        } /* if */
    6058      } /* for d */
Note: See TracChangeset for help on using the changeset viewer.