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

Add 64/48 bit LBA support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.
Note: See TracChangeset for help on using the changeset viewer.