Changeset 82 for trunk/src/os2ahci/ata.c


Ignore:
Timestamp:
Mar 2, 2011, 11:48:03 PM (14 years ago)
Author:
chris
Message:

Version 1.09
============

  • Added new command line parameter, "/4", which will force a track size of 56 sectors to be reported in geometry requests. This will improve performance for newer HDs with 4K sectors and file systems which use block sizes larger than 512 bytes (FAT, JFS, ...) because all partitions will be aligned on 4K (8 sector) boundaries.
  • Changed AP_DEVICE parameter to ata_cmd() from 16 bits to 8 bits -- the corresponding field in ATA_CMD has always been 8 bits and there's no point discarding the lower 8 bits of the AP_DEVICE parameter as a general rule. Besides, it confused me in the end...
  • Always return some kind of error in ata_req_sense() because this function will only be called when we received an error interrupt; atapi_req_sense() already does this.
  • Cosmetic changes
File:
1 edited

Legend:

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

    r80 r82  
    137137      /* ATA device byte; note that this byte contains the highest
    138138       * 4 bits of LBA-28 address; we have to leave them alone here. */
    139       ata_cmd.device |= (va_arg(va, u16) & 0xf000U) >> 8;
     139      ata_cmd.device |= va_arg(va, u16) & 0xf0U;
    140140      break;
    141141
     
    202202  memset(cmd_hdr, 0x00, sizeof(*cmd_hdr));
    203203  cmd_hdr->options  = ((d & 0x0f) << 12);
    204   cmd_hdr->options |= ahci_flags;  /* AHCI commaand flags */
     204  cmd_hdr->options |= ahci_flags;  /* AHCI command flags */
    205205  cmd_hdr->options |= 5;           /* length of command FIS in 32-bit words */
    206206  cmd_hdr->tbl_addr = dma_base_phys + offsetof(AHCI_PORT_DMA, cmd_tbl[slot]);
     
    435435  USHORT geometry_len =  ((IORB_GEOMETRY _far *) iorb)->GeometryLen;
    436436  u16 *id_buf = add_workspace(iorb)->buf;
     437  int a = iorb_unit_adapter(iorb);
     438  int p = iorb_unit_port(iorb);
    437439
    438440  /* Fill-in geometry information; the ATA-8 spec declares the geometry
     
    444446   *  - 512 bytes per sector
    445447   *  - 255 heads
    446    *  -  63 sectors per track
     448   *  -  63 sectors per track (or 56 with the parameter "/4")
    447449   *  -   x cylinders (calculated)
    448450   *
    449    * Please note that os2ahci currently does not support ATA sectors larger
    450    * than 512 bytes, therefore relies on the translation logic built into the
    451    * corresponding ATA disks. In theory, partitions should be aligned to the
    452    * large sectors to prevent needless mapping all over the place but HPFS
    453    * uses logical block sizes smaller than the typical large sectors found on
    454    * modern hard disks so this won't make much of a difference. Large sector
    455    * support will be evaluated at a later time (it's unclear right now whether
    456    * HPFS would even support anything larger than 512 bytes).
     451   * Please note that os2ahci currently does not natively support ATA sectors
     452   * larger than 512 bytes, therefore relies on the translation logic built
     453   * into the corresponding ATA disks. In order to prevent file systems that
     454   * use block sizes larger than 512 bytes (FAT, JFS, ...) from ending up on
     455   * incorrectly aligned physical sector accesses, hence using more physical
     456   * I/Os than necessary, the command line parameter "/4" can be used to force
     457   * a track size of 56 sectors. This way, partitions will start on 4K
     458   * boundaries.
    457459   *
    458460   * Another limitation is that OS/2 has a 32-bit variable for the total number
     
    464466   */
    465467  memset(geometry, 0x00, geometry_len);
    466   geometry->BytesPerSector  = 512;
     468  geometry->BytesPerSector = ATA_SECTOR_SIZE;
    467469
    468470  /* extract total number of sectors */
     
    483485  }
    484486
    485   /* see whether the "current" (read: BIOS-supplied) geometry looks OK */
    486   if (CUR_HEADS(id_buf) > 0 && CUR_CYLS(id_buf) > 0 &&
    487       CUR_SECTORS(id_buf) > 0 &&
    488       CUR_CAPACITY(id_buf) == CUR_HEADS(id_buf) *
    489                               CUR_CYLS(id_buf) *
    490                               CUR_SECTORS(id_buf)) {
    491     /* use BIOS-supplied values for geometry */
     487  /* fabricate the remaining geometry fields */
     488  if (track_size[a][p] != 0) {
     489    /* A specific track size has been requested for this port; this is
     490     * typically done for disks with 4K sectors to make sure partitions
     491     * start on 8-sector boundaries (parameter "/4").
     492     */
     493    geometry->NumHeads        = 255;
     494    geometry->SectorsPerTrack = track_size[a][p];
     495    geometry->TotalCylinders  = geometry->TotalSectors /
     496                                 ((u32) geometry->NumHeads *
     497                                  (u32) geometry->SectorsPerTrack);
     498
     499  } else if (CUR_HEADS(id_buf) > 0 && CUR_CYLS(id_buf) > 0 &&
     500             CUR_SECTORS(id_buf) > 0 &&
     501             CUR_CAPACITY(id_buf) == CUR_HEADS(id_buf) *
     502                                     CUR_CYLS(id_buf) *
     503                                     CUR_SECTORS(id_buf)) {
     504    /* BIOS-supplied (aka "current") geometry values look valid */
    492505    geometry->NumHeads        = CUR_HEADS(id_buf);
    493506    geometry->SectorsPerTrack = CUR_SECTORS(id_buf);
     
    496509  } else if (ATA_HEADS(id_buf) > 0 && ATA_CYLS(id_buf) > 0 &&
    497510             ATA_SECTORS(id_buf) > 0) {
    498     /* use ATA-supplied values for geometry */
     511    /* ATA-supplied values for geometry look valid */
    499512    geometry->NumHeads        = ATA_HEADS(id_buf);
    500513    geometry->SectorsPerTrack = ATA_SECTORS(id_buf);
     
    549562  int d = iorb_unit_device(iorb);
    550563  int rc;
     564
     565  /* Kludge: some I/O commands during boot use excessive S/G buffer lengths
     566   * which cause NCQ commands to lock up. If there's only one S/G element
     567   * and this element is already larger than what we can derive from the sector
     568   * count, we'll adjust that element.
     569   */
     570  if (io->BlocksXferred == 0 && io->cSGList == 1 &&
     571      io->pSGList[0].XferBufLen > io->BlockCount * io->BlockSize) {
     572    io->pSGList[0].XferBufLen = io->BlockCount * io->BlockSize;
     573  }
    551574
    552575  /* prepare read command while keeping an eye on S/G count limitations */
     
    568591                     AP_COUNT,     (u16) (slot << 3), /* tag = slot */
    569592                     AP_SGLIST,    io->pSGList + sg_indx, (u16) sg_cnt,
    570                      AP_DEVICE,    0x4000,
     593                     AP_DEVICE,    0x40,
    571594                     AP_END);
    572595      } else {
     
    575598                     AP_COUNT,     (u16) count,
    576599                     AP_SGLIST,    io->pSGList + sg_indx, (u16) sg_cnt,
    577                      AP_DEVICE,    0x4000,
     600                     AP_DEVICE,    0x40,
    578601                     AP_END);
    579602      }
     
    584607                   AP_COUNT,     (u16) count & 0xffU,
    585608                   AP_SGLIST,    io->pSGList + sg_indx, (u16) sg_cnt,
    586                    AP_DEVICE,    0x4000,
     609                   AP_DEVICE,    0x40,
    587610                   AP_END);
    588611    }
     
    650673                 AP_SECTOR_48, (u32) io->RBA, (u16) 0,
    651674                 AP_COUNT,     (u16) io->BlockCount,
    652                  AP_DEVICE,    0x4000,
     675                 AP_DEVICE,    0x40,
    653676                 AP_END);
    654677  } else {
     
    695718                     AP_COUNT,     (u16) (slot << 3), /* tag = slot */
    696719                     AP_SGLIST,    io->pSGList + sg_indx, (u16) sg_cnt,
    697                      AP_DEVICE,    0x4000,
     720                     AP_DEVICE,    0x40,
    698721                     AP_DEVICE,    (io->Flags & XIO_DISABLE_HW_WRITE_CACHE) ?
    699                                    0x8000 : 0, /* force unit access */
     722                                   0x80 : 0, /* force unit access */
    700723                     AP_WRITE,     1,
    701724                     AP_END);
     
    705728                     AP_COUNT,     (u16) count,
    706729                     AP_SGLIST,    io->pSGList + sg_indx, (u16) sg_cnt,
    707                      AP_DEVICE,    0x4000,
     730                     AP_DEVICE,    0x40,
    708731                     AP_WRITE,     1,
    709732                     AP_END);
     
    715738                   AP_COUNT,     (u16) count & 0xffU,
    716739                   AP_SGLIST,    io->pSGList + sg_indx, (u16) sg_cnt,
    717                    AP_DEVICE,    0x4000,
     740                   AP_DEVICE,    0x40,
    718741                   AP_WRITE,     1,
    719742                   AP_END);
     
    826849      iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
    827850    }
     851  } else {
     852    /* this function only gets called when we received an error interrupt */
     853    iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
    828854  }
    829855
Note: See TracChangeset for help on using the changeset viewer.