Changeset 207
- Timestamp:
- Feb 23, 2021, 10:10:11 PM (4 years ago)
- 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.081 AHCI Driver for OS/2 2 2 3 3 Introduction … … 77 77 use this switch. 78 78 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: 80 80 1 = COM1 81 81 2 = COM2 … … 388 388 Change Log 389 389 ========== 390 v.2.08 01-Jan-2021 - David Azarewicz390 v.2.08 20-Feb-2021 - David Azarewicz 391 391 Corrected RM ADD handle and unit. 392 392 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. 393 395 394 396 v.2.07 19-May-2019 - David Azarewicz -
trunk/src/os2ahci/ahci.c
r205 r207 79 79 u32 version; 80 80 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", 82 82 ad_no(ai), 83 83 PCI_BUS_FROM_BDF(ai->bus_dev_func), PCI_DEV_FROM_BDF(ai->bus_dev_func), 84 84 PCI_FUNC_FROM_BDF(ai->bus_dev_func), ai->irq, ai->mmio_phys); 85 85 86 for (i = 0; i <= HOST_CAP2; i += sizeof(u32)) { 86 for (i = 0; i <= HOST_CAP2; i += sizeof(u32)) 87 { 87 88 u32 val; 88 89 … … 98 99 dprintf(0," %02x: %08lx", i, val); 99 100 100 if (i == HOST_CAP) { 101 if (i == HOST_CAP) 102 { 101 103 dprintf(0," -"); 102 104 if (val & HOST_CAP_64) dprintf(0," 64bit"); … … 119 121 dprintf(0," cmd_slots:%d", ((val >> 8) & 0x1f) + 1); 120 122 dprintf(0," ports:%d", (val & 0x1f) + 1); 121 } else if (i == HOST_CTL) { 123 } 124 else if (i == HOST_CTL) 125 { 122 126 dprintf(0," -"); 123 127 if (val & HOST_AHCI_EN) dprintf(0," ahci_enabled"); 124 128 if (val & HOST_IRQ_EN) dprintf(0," irq_enabled"); 125 129 if (val & HOST_RESET) dprintf(0," resetting"); 126 } else if (i == HOST_CAP2) { 130 } 131 else if (i == HOST_CAP2) 132 { 127 133 dprintf(0," -"); 128 134 if (val & HOST_CAP2_BOH) dprintf(0," boh"); … … 278 284 } 279 285 280 DUMP_HOST_REGS( 2,ai,1);286 DUMP_HOST_REGS(6,ai,1); 281 287 282 288 return(0); … … 529 535 int i; 530 536 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)); 532 538 533 539 if (!ai->int_set) … … 609 615 /* pci_enable_int(ai->bus, ai->dev_func); */ 610 616 611 DPRINTF( 1,__func__": done\n");617 DPRINTF(2,__func__": done\n"); 612 618 return(0); 613 619 } … … 834 840 { 835 841 /* 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); 837 843 838 844 #ifdef DAZ_NEW_CODE … … 909 915 TIMER Timer; 910 916 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); 913 919 914 920 /* stop port engines (we don't care whether there is an error doing so) */ … … 944 950 945 951 /* wait for communication to be re-established after port reset */ 946 DPRINTF( 2,"Wait for communication...\n");952 DPRINTF(3,"Wait for communication...\n"); 947 953 TimerInit(&Timer, 500); 948 954 while (((tmp = readl(port_mmio + PORT_SCR_STAT)) & 3) != 3) … … 950 956 if (TimerCheckAndBlock(&Timer)) 951 957 { 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); 953 959 return(-1); 954 960 } … … 960 966 961 967 /* 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); 963 969 ahci_start_port(ai, p, ei); 964 970 … … 1794 1800 } 1795 1801 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 1797 1810 1798 1811 /* Handle device-specific errors. Those errors typically involve restarting -
trunk/src/os2ahci/ata.c
r205 r207 26 26 */ 27 27 28 #define INCL_LONGLONG 28 29 #include "os2ahci.h" 29 30 #include "ata.h" 30 31 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) 40 33 41 34 /****************************************************************************** … … 256 249 { 257 250 u32 chunk = (sg_size > AHCI_MAX_SG_ELEMENT_LEN) ? AHCI_MAX_SG_ELEMENT_LEN : sg_size; 251 258 252 if (n >= AHCI_MAX_SG) 259 253 { 260 254 /* 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"); 262 261 return(i - 1); 263 262 } … … 341 340 342 341 /****************************************************************************** 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 HW348 * limit will never cross sector boundaries. This means that splitting349 * S/G lists into multiple commands can be done without editing the S/G350 * 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 /******************************************************************************367 342 * Get max S/G count which will fit into our HW S/G buffers. This function is 368 343 * called when the S/G list is too long and we need to split the IORB into … … 459 434 * geometry to the last full cylinder. 460 435 */ 461 int adjust_cylinders(GEOMETRY *geometry, ULONG TotalSectors)436 int adjust_cylinders(GEOMETRY64 *geometry, ULONG TotalSectors) 462 437 { 463 438 USHORT SecPerCyl; … … 487 462 #define BIOS_MAX_NUMHEADS 255 488 463 #define BIOS_MAX_SECTORSPERTRACK 63 489 void log_geom_calculate_LBA_assist(GEOMETRY *geometry, ULONG TotalSectors)464 void log_geom_calculate_LBA_assist(GEOMETRY64 *geometry, ULONG TotalSectors) 490 465 { 491 466 UCHAR numSpT = BIOS_MAX_SECTORSPERTRACK; … … 524 499 DLA_Table_Sector *pDLA = (DLA_Table_Sector*)add_workspace(pIorb)->buf; 525 500 AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb); 526 GEOMETRY *geometry =((IORB_GEOMETRY*)pIorb)->f16Geometry;501 GEOMETRY64 *geometry = (GEOMETRY64*)((IORB_GEOMETRY*)pIorb)->f16Geometry; 527 502 int p = iorb_unit_port(pIorb); 528 503 int rc; … … 544 519 geometry->NumHeads = pDLA->Heads_Per_Cylinder; 545 520 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; 547 525 return 1; 548 526 } … … 589 567 void ata_get_geometry_pp(IORBH FAR16DATA *vIorb, IORBH *pIorb) 590 568 { 591 GEOMETRY *geometry =((IORB_GEOMETRY*)pIorb)->f16Geometry;569 GEOMETRY64 *geometry = (GEOMETRY64*)((IORB_GEOMETRY*)pIorb)->f16Geometry; 592 570 USHORT geometry_len = ((IORB_GEOMETRY *)pIorb)->GeometryLen; 571 ULONGLONG ullTotalSectors; 593 572 u16 *id_buf = add_workspace(pIorb)->buf; 594 573 int a = iorb_unit_adapter(pIorb); … … 627 606 * can be unexpected and catastrophic. 628 607 */ 629 memset(geometry, 0 x00, geometry_len);608 memset(geometry, 0, geometry_len); 630 609 geometry->BytesPerSector = ATA_SECTOR_SIZE; 631 610 … … 634 613 { 635 614 /* 48-bit LBA supported */ 636 if ( ATA_CAPACITY48_H(id_buf) != 0)615 if ((ATA_CAPACITY48_H(id_buf) != 0) && !add_workspace(pIorb)->fIs64bit) 637 616 { 638 617 /* more than 32 bits for number of sectors */ … … 640 619 iorb_unit_adapter(pIorb), iorb_unit_port(pIorb), 641 620 iorb_unit_device(pIorb)); 642 geometry->TotalSectors = 0xffffffffUL;621 ullTotalSectors = 0xffffffff; 643 622 } 644 623 else 645 624 { 646 geometry->TotalSectors = ATA_CAPACITY48_L(id_buf);625 ullTotalSectors = MAKEULL(ATA_CAPACITY48_H(id_buf), ATA_CAPACITY48_L(id_buf)); 647 626 } 648 627 } … … 650 629 { 651 630 /* 28-bit LBA */ 652 geometry->TotalSectors = ATA_CAPACITY(id_buf) & 0x0fffffffUL;631 ullTotalSectors = ATA_CAPACITY(id_buf) & 0x0fffffff; 653 632 } 654 633 … … 663 642 geometry->NumHeads = 255; 664 643 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); 666 645 Method = "Custom"; 667 646 } … … 688 667 geometry->NumHeads = 255; 689 668 geometry->SectorsPerTrack = 63; 690 geometry->TotalCylinders = geometry->TotalSectors / ((u32) geometry->NumHeads * (u32)geometry->SectorsPerTrack);669 geometry->TotalCylinders = ullTotalSectors / ((u32)geometry->NumHeads * (u32)geometry->SectorsPerTrack); 691 670 Method = "SCSI"; 692 671 } … … 694 673 DPRINTF(2,"Physical geometry: %d cylinders, %d heads, %d sectors per track (%dMB) (%s)\n", 695 674 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 711 701 ad_infos[a].ports[p].devs[0].dev_info.Cylinders = geometry->TotalCylinders; 712 702 ad_infos[a].ports[p].devs[0].dev_info.HeadsPerCylinder = geometry->NumHeads; 713 703 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; 715 705 ad_infos[a].ports[p].devs[0].dev_info.Method = Method; 716 706 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", 718 709 geometry->TotalCylinders, geometry->NumHeads, geometry->SectorsPerTrack, 719 ( geometry->TotalSectors / 2048), Method);710 (ULONG)(ullTotalSectors / 2048), Method); 720 711 721 712 /* tell interrupt handler that this IORB is complete */ … … 737 728 738 729 /****************************************************************************** 730 * Fabricate ATA READ command based on the capabilities of the corresponding 731 * device and the paramters set from above (NCQ, etc). 732 */ 733 static 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 /****************************************************************************** 739 783 * Read sectors from AHCI device. 740 784 */ … … 744 788 SCATGATENTRY *pSGList = (SCATGATENTRY*)Far16ToFlat(io->f16SGList); 745 789 AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb); 746 ULONG sector= io->RBA + io->BlocksXferred;790 ULONGLONG ullLba = io->RBA + io->BlocksXferred; 747 791 USHORT count = io->BlockCount - io->BlocksXferred; 748 792 USHORT sg_indx; … … 762 806 /* unaligned S/G addresses present; need to use double buffers */ 763 807 return(ata_read_unaligned(pIorb, slot)); 808 } 809 810 if (add_workspace(pIorb)->fIs64bit) 811 { 812 ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA + io->BlocksXferred; 764 813 } 765 814 … … 778 827 do 779 828 { 780 sg_indx = ata_get_sg_indx(io);829 sg_indx = SgIndexFromOffset(pSGList, io->cSGList, io->BlocksXferred * io->BlockSize); 781 830 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) 784 833 { 785 834 /* couldn't map all S/G elements */ … … 802 851 add_workspace(pIorb)->unaligned = 1; 803 852 return(ata_read_unaligned(pIorb, slot)); 804 805 853 } 806 854 else … … 823 871 ADD_WORKSPACE *aws = add_workspace(pIorb); 824 872 AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb); 825 ULONG sector= io->RBA + io->BlocksXferred;873 ULONGLONG ullLba = io->RBA + io->BlocksXferred; 826 874 SCATGATENTRY sg_single; 827 875 int p = iorb_unit_port(pIorb); … … 829 877 int rc; 830 878 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); 832 885 ai->ports[p].unaligned_read_count++; 833 886 … … 842 895 sg_single.ppXferBuf = MemPhysAdr(aws->buf); 843 896 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); 845 898 846 899 if (rc == 0) { … … 873 926 { 874 927 /* 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); 878 930 } 879 931 … … 902 954 int p = iorb_unit_port(pIorb); 903 955 int d = iorb_unit_device(pIorb); 956 ULONGLONG ullLba = io->RBA; 904 957 int rc; 905 958 … … 910 963 } 911 964 965 if (add_workspace(pIorb)->fIs64bit) 966 { 967 ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA; 968 } 969 912 970 /* prepare verify command */ 913 if ( io->RBA>= (1UL << 28) || io->BlockCount > 256)971 if (ullLba >= (1UL << 28) || io->BlockCount > 256) 914 972 { 915 973 /* need LBA48 for this command */ … … 919 977 } 920 978 rc = ata_cmd(ai, p, d, slot, ATA_CMD_VERIFY_EXT, 921 AP_SECTOR_48, io->RBA, 0,979 AP_SECTOR_48, ullLba, 922 980 AP_COUNT, io->BlockCount, 923 981 AP_DEVICE, 0x40, … … 925 983 } else { 926 984 rc = ata_cmd(ai, p, d, slot, ATA_CMD_VERIFY, 927 AP_SECTOR_28, io->RBA,985 AP_SECTOR_28, (ULONG)ullLba, 928 986 AP_COUNT, io->BlockCount & 0xffU, 929 987 AP_DEVICE, 0x40, … … 935 993 936 994 /****************************************************************************** 995 * Fabricate ATA WRITE command based on the capabilities of the corresponding 996 * device and the paramters set from above (NCQ, etc) 997 */ 998 static 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 /****************************************************************************** 937 1053 * Write sectors to AHCI device. 938 1054 */ … … 942 1058 SCATGATENTRY *pSGList = (SCATGATENTRY*)Far16ToFlat(io->f16SGList); 943 1059 AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb); 944 ULONG sector= io->RBA + io->BlocksXferred;1060 ULONGLONG ullLba = io->RBA + io->BlocksXferred; 945 1061 USHORT count = io->BlockCount - io->BlocksXferred; 946 1062 USHORT sg_indx; … … 962 1078 } 963 1079 1080 if (add_workspace(pIorb)->fIs64bit) 1081 { 1082 ullLba = ((IORB_EXECUTEIO64*)pIorb)->ullRBA + io->BlocksXferred; 1083 } 1084 964 1085 /* prepare write command while keeping an eye on S/G count limitations */ 965 1086 do { 966 sg_indx = ata_get_sg_indx(io);1087 sg_indx = SgIndexFromOffset(pSGList, io->cSGList, io->BlocksXferred * io->BlockSize); 967 1088 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, 969 1090 pSGList + sg_indx, sg_cnt, 970 1091 io->Flags & XIO_DISABLE_HW_WRITE_CACHE)) > 0) 971 1092 { 972 1093 /* couldn't map all S/G elements */ 973 ata_max_sg_cnt(io, sg_indx, (USHORT) 1094 ata_max_sg_cnt(io, sg_indx, (USHORT)rc, &sg_cnt, &count); 974 1095 } 975 1096 } while (rc > 0 && sg_cnt > 0); … … 1010 1131 ADD_WORKSPACE *aws = add_workspace(pIorb); 1011 1132 AD_INFO *ai = ad_infos + iorb_unit_adapter(pIorb); 1012 ULONG sector= io->RBA + io->BlocksXferred;1133 ULONGLONG ullLba = io->RBA + io->BlocksXferred; 1013 1134 SCATGATENTRY sg_single; 1014 1135 int p = iorb_unit_port(pIorb); … … 1016 1137 int rc; 1017 1138 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); 1019 1145 1020 1146 /* allocate transfer buffer */ … … 1026 1152 1027 1153 /* 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); 1031 1156 1032 1157 /* prepare write command using transfer buffer */ 1033 1158 sg_single.ppXferBuf = MemPhysAdr(aws->buf); 1034 1159 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, 1036 1161 io->Flags & XIO_DISABLE_HW_WRITE_CACHE); 1037 1162 … … 1250 1375 1251 1376 /****************************************************************************** 1252 * Fabricate ATA READ command based on the capabilities of the corresponding1253 * 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 else1281 {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 else1292 {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 corresponding1306 * 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 else1338 {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 else1349 {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 else1395 {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 /******************************************************************************1408 1377 * Halt processing by submitting an internal error. This is a last resort and 1409 1378 * should only be called when the system state is corrupt. -
trunk/src/os2ahci/ata.h
r205 r207 492 492 extern int v_ata_cmd(AD_INFO *ai, int port, int device, int slot, int cmd, va_list va); 493 493 extern void ata_cmd_to_fis(u8 *fis, ATA_CMD *cmd, int device); 494 extern USHORT ata_get_sg_indx(IORB_EXECUTEIO *io);495 494 extern void ata_max_sg_cnt(IORB_EXECUTEIO *io, USHORT sg_indx, USHORT sg_max, USHORT *sg_cnt, USHORT *sector_cnt); 496 497 495 extern int ata_get_geometry(IORBH FAR16DATA *iorb, IORBH *pIorb, int slot); 498 496 extern void ata_get_geometry_pp(IORBH FAR16DATA *vIorb, IORBH *pIorb); … … 508 506 extern void ata_execute_ata_pp(IORBH FAR16DATA *vIorb, IORBH *pIorb); 509 507 extern int ata_req_sense(IORBH FAR16DATA *vIorb, IORBH *pIorb, int slot); 510 511 508 extern char *ata_dev_name(u16 *id_buf); 512 509 -
trunk/src/os2ahci/atapi.c
r205 r207 99 99 100 100 /* 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); 102 102 sg_cnt = io->cSGList - sg_indx; 103 103 -
trunk/src/os2ahci/os2ahci.c
r206 r207 89 89 int suspended; 90 90 int resume_sleep_flag; 91 AHCISTATS AhciStats; 91 92 92 93 /* apapter/port-specific options saved when parsing the command line */ … … 189 190 UtSetDriverName("OS2AHCI$"); 190 191 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; 191 195 192 196 /* create driver-level spinlock */ … … 219 223 } 220 224 221 if (ArgCmp(pszCmdLine, "C :"))222 { 223 pszCmdLine += 2;225 if (ArgCmp(pszCmdLine, "COM:")) 226 { 227 pszCmdLine += 4; 224 228 /* set COM port base address for debug messages */ 225 229 D32g_ComBase = strtol(pszCmdLine, &pszCmdLine, 0); … … 483 487 { 484 488 DPRINTF(2,"IOCTL 0x%x/0x%x\n", ioctl->ioctl.bCategory, ioctl->ioctl.bFunction); 489 AhciStats.ulTestCount2++; 485 490 486 491 switch (ioctl->ioctl.bCategory) … … 803 808 break; 804 809 810 case IOCC_GEOMETRY_64: 811 add_workspace(pIorb)->fIs64bit = 1; 812 /* fall thru */ 805 813 case IOCC_GEOMETRY: 806 814 iocc_geometry(vIorb, pIorb); 807 815 break; 808 816 817 case IOCC_EXECUTE_IO_64: 818 add_workspace(pIorb)->fIs64bit = 1; 819 /* fall thru */ 809 820 case IOCC_EXECUTE_IO: 810 821 iocc_execute_io(vIorb, pIorb); … … 816 827 817 828 case IOCC_ADAPTER_PASSTHRU: 829 AhciStats.ulTestCount1++; 818 830 iocc_adapter_passthru(vIorb, pIorb); 819 831 break; … … 1215 1227 1216 1228 case IOCM_WRITE: 1217 add_workspace(pIorb)->idempotent = 1;1218 ahci_write(vIorb, pIorb);1219 break;1220 1221 1229 case IOCM_WRITE_VERIFY: 1222 1230 add_workspace(pIorb)->idempotent = 1; -
trunk/src/os2ahci/os2ahci.h
r205 r207 230 230 231 231 typedef struct { 232 U SHORTCylinders;232 ULONG Cylinders; 233 233 USHORT HeadsPerCylinder; 234 234 USHORT SectorsPerTrack; 235 ULONG TotalSectors;235 ULONGLONG TotalSectors; 236 236 char *Method; 237 237 } DEV_INFO; … … 248 248 u32 dma_buf_phys; /* 14 physical address of DMA scratch buffer */ 249 249 u8 *dma_buf; /* 18 DMA scatch buffers */ 250 u32 unaligned_read_count; 251 u32 error_count; 252 u32 ulResetCount; /* added in 2.07 */ 250 253 251 254 struct { /* 1c */ … … 263 266 char dev_name[AHCI_DEV_NAME_LEN]; 264 267 } devs[AHCI_MAX_DEVS]; 265 266 u32 unaligned_read_count;267 u32 error_count;268 u32 ulResetCount; /* added in 2.07 */269 268 } P_INFO; 270 269 … … 313 312 unsigned short processing :1; /* 0e IORB is being processd */ 314 313 unsigned short idempotent :1; /* IORB is idempotent (can be retried) */ 314 unsigned short fIs64bit :1; /* Transaction is a 64 bit operation */ 315 315 unsigned short queued_hw :1; /* IORB has been queued to hardware */ 316 316 unsigned short no_ncq :1; /* must not use native command queuing */ … … 354 354 /* These are the four entries which correspond to the entries in the partition table. */ 355 355 } DLA_Table_Sector, *PDLA_Table_Sector; 356 357 typedef struct _ahcistats_ 358 { 359 ULONG ulSize; 360 ULONG ulVersion; 361 ULONG ulTestCount3; 362 ULONG ulTestCount2; 363 ULONG ulTestCount1; 364 } AHCISTATS; 356 365 357 366 static inline unsigned long readl(void *a) … … 487 496 extern int suspended; /* indicates if the driver is suspended */ 488 497 extern int resume_sleep_flag; 498 extern AHCISTATS AhciStats; 489 499 490 500 /* port restart context hook and input data */ -
trunk/src/os2ahci/trace.c
r205 r207 5 5 */ 6 6 7 #define INCL_LONGLONG 7 8 #include "os2ahci.h" 8 9 … … 37 38 if (pi->devs[d].present) 38 39 { 39 if (iFlag) dprintf(0," Port %d: \n", p);40 if (iFlag) dprintf(0," Port %d:", p); 40 41 iFlag = 0; 41 dprintf(0," Drive %d:", d);42 42 if (pi->devs[d].atapi) dprintf(0," atapi"); 43 43 if (pi->devs[d].removable) dprintf(0," removable"); … … 46 46 dprintf(0," %d cylinders, %d heads, %d sectors per track (%dMB) (%s)", 47 47 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); 49 49 } 50 if (pi->devs[d].ignored) dprintf(0," Not a usable disk");50 if (pi->devs[d].ignored) dprintf(0," Unusable"); 51 51 dprintf(0,"\n"); 52 dprintf(0," 52 dprintf(0," Model: %s\n", pi->devs[d].dev_name); 53 53 } 54 54 else if (verbosity > 0) 55 55 { 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); 59 57 } /* if */ 60 58 } /* for d */
Note:
See TracChangeset
for help on using the changeset viewer.