- Timestamp:
- May 8, 2013, 5:10:33 PM (12 years ago)
- Location:
- trunk/src/os2ahci
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/os2ahci/Makefile
r156 r157 97 97 # Main dependencies 98 98 99 LIBS = addcalls doscalls rmcalls apmcalls 99 LIBS = addcalls doscalls rmcalls apmcalls os2286p.lib 100 100 101 101 SRCS = init.asm math.asm libc.c os2ahci.c pci.c ahci.c ata.c atapi.c & -
trunk/src/os2ahci/README
r156 r157 405 405 Debug output improvements. 406 406 Added /b switch for setting debug baud rate. 407 Fixed up time delay functions 407 408 408 409 v.1.26 26-Mar-2013 - David Azarewicz -
trunk/src/os2ahci/ahci.c
r156 r157 331 331 332 332 /* spec says "leave reset bit on for at least 1ms"; make it 2ms */ 333 mdelay(2);333 udelay(2000); 334 334 335 335 writel(port_mmio + PORT_SCR_CTL, tmp); … … 341 341 * least hard disks complete the reset within a few milliseonds) 342 342 */ 343 m delay(20);343 msleep(20); 344 344 } 345 345 … … 448 448 return(0); 449 449 } 450 m delay(10);450 msleep(10); 451 451 } 452 452 … … 459 459 { 460 460 u32 tmp; 461 int timeout = 1000;461 TIMER Timer; 462 462 463 463 dprintf("controller reset starting on adapter %d\n", ad_no(ai)); … … 480 480 * the hardware should be considered fried. 481 481 */ 482 while (((tmp = readl(ai->mmio + HOST_CTL)) & HOST_RESET) == HOST_RESET) { 483 mdelay(10); 484 timeout -= 10; 485 if (timeout <= 0) { 486 dprintf("controller reset failed (0x%lx)\n", tmp); 487 return(-1); 488 } 482 timer_init(&Timer, 1000); 483 while (((tmp = readl(ai->mmio + HOST_CTL)) & HOST_RESET) != 0) { 484 if (timer_check_and_block(&Timer)) { 485 dprintf("controller reset failed (0x%lx)\n", tmp); 486 return(-1); 487 } 489 488 } 490 489 … … 497 496 ahci_restore_initial_config(ai); 498 497 499 500 501 502 503 504 505 506 507 508 509 510 498 if (ai->pci->vendor == PCI_VENDOR_ID_INTEL) { 499 u32 tmp16 = 0; 500 501 ddprintf("ahci_reset_controller: intel detected\n"); 502 /* configure PCS */ 503 pci_read_conf(ai->bus, ai->dev_func, 0x92, sizeof(u16), &tmp16); 504 if ((tmp16 & ai->port_map) != ai->port_map) { 505 ddprintf("ahci_reset_controller: updating PCS %x/%x\n", (u16)tmp16, ai->port_map); 506 tmp16 |= ai->port_map; 507 pci_write_conf(ai->bus, ai->dev_func, 0x92, sizeof(u16), tmp16); 508 } 509 } 511 510 512 511 return 0; … … 538 537 int p; 539 538 int i; 539 TIMER Timer; 540 540 541 541 if ((id_buf = malloc(ATA_ID_WORDS * sizeof(u16))) == NULL) { … … 561 561 ddprintf("ahci_scan_ports: Wait till not busy on port %d\n", p); 562 562 /* wait until all active commands have completed on this port */ 563 timer_init(&Timer, 250); 563 564 while (ahci_port_busy(ai, p)) { 564 msleep(250);565 if (timer_check_and_block(&Timer)) break; 565 566 } 566 567 … … 718 719 u8 _far *port_mmio = port_base(ai, p); 719 720 u32 tmp; 720 int timeout;721 TIMER Timer; 721 722 722 723 dprintf("ahci_reset_port: resetting port %d.%d\n", ad_no(ai), p); … … 762 763 763 764 /* spec says "leave reset bit on for at least 1ms"; make it 2ms */ 764 mdelay(2);765 udelay(2000); 765 766 766 767 writel(port_mmio + PORT_SCR_CTL, tmp); … … 768 769 769 770 /* wait for communication to be re-established after port reset */ 770 timeout = 5000; 771 dprintf("Wait for communication...\n"); 772 timer_init(&Timer, 500); 771 773 while (((tmp = readl(port_mmio + PORT_SCR_STAT)) & 3) != 3) { 772 mdelay(10); 773 timeout -= 10; 774 if (timeout <= 0) { 775 dprintf("no device present after resetting port #%d " 776 "(PORT_SCR_STAT = 0x%lx)\n", p, tmp); 774 if (timer_check_and_block(&Timer)) { 775 dprintf("no device present after resetting port #%d (PORT_SCR_STAT = 0x%lx)\n", p, tmp); 777 776 return(-1); 778 777 } … … 788 787 789 788 /* wait for device to be ready ((PxTFD & (BSY | DRQ | ERR)) == 0) */ 790 time out = 5000;789 timer_init(&Timer, 1000); 791 790 while (((tmp = readl(port_mmio + PORT_TFDATA)) & 0x89) != 0) { 792 mdelay(10); 793 timeout -= 10; 794 if (timeout <= 0) { 795 dprintf("device not ready on port #%d " 796 "(PORT_TFDATA = 0x%lx)\n", p, tmp); 791 if (timer_check_and_block(&Timer)) { 792 dprintf("device not ready on port #%d (PORT_TFDATA = 0x%lx)\n", p, tmp); 797 793 ahci_stop_port(ai, p); 798 794 return(-1); 799 795 } 800 796 } 801 ddprintf("ahci_reset_port: PORT_TFDATA 797 ddprintf("ahci_reset_port: PORT_TFDATA = 0x%lx\n", readl(port_mmio + PORT_TFDATA)); 802 798 803 799 return(0); … … 949 945 { 950 946 u8 _far *port_mmio = port_base(ai, p); 951 int timeout = 1000;947 TIMER Timer; 952 948 u32 tmp; 949 int status; 953 950 954 951 /* disable FIS reception */ … … 958 955 959 956 /* wait for completion, spec says 500ms, give it 1000ms */ 960 while (timeout > 0 && (readl(port_mmio + PORT_CMD) & PORT_CMD_FIS_ON)) { 961 mdelay(10); 962 timeout -= 10; 963 } 964 965 return((timeout <= 0) ? -1 : 0); 957 status = 0; 958 timer_init(&Timer, 1000); 959 while (readl(port_mmio + PORT_CMD) & PORT_CMD_FIS_ON) { 960 status = timer_check_and_block(&Timer); 961 if (status) break; 962 } 963 964 return(status ? -1 : 0); 966 965 } 967 966 … … 976 975 { 977 976 u8 _far *port_mmio = port_base(ai, p); 978 int timeout = 500; 977 TIMER Timer; 978 int status; 979 979 u32 tmp; 980 980 … … 991 991 992 992 /* wait for engine to stop. This could be as long as 500 msec */ 993 while (timeout > 0 && (readl(port_mmio + PORT_CMD) & PORT_CMD_LIST_ON)) { 994 mdelay(10); 995 timeout -= 10; 996 } 997 998 return((timeout <= 0) ? -1 : 0); 993 status = 0; 994 timer_init(&Timer, 500); 995 while (readl(port_mmio + PORT_CMD) & PORT_CMD_LIST_ON) { 996 status = timer_check_and_block(&Timer); 997 if (status) break; 998 } 999 1000 return(status ? -1 : 0); 999 1001 } 1000 1002 … … 1162 1164 int p = iorb_unit_port(iorb); 1163 1165 u8 _far *port_mmio = port_base(ai, p); 1166 TIMER Timer; 1167 int rc; 1164 1168 1165 1169 /* enable AHCI mode */ … … 1204 1208 ddprintf("executing polled cmd on slot 0..."); 1205 1209 writel(port_mmio + PORT_CMD_ISSUE, 1); 1206 timeout /= 10; 1207 while (timeout > 0 && (readl(port_mmio + PORT_CMD_ISSUE) & 1)) { 1208 mdelay(10); 1209 timeout--; 1210 } 1211 ddprintf(" done (time left = %ld)\n", timeout * 10); 1212 1213 if (timeout == 0) { 1210 timer_init(&Timer, timeout); 1211 while (readl(port_mmio + PORT_CMD_ISSUE) & 1) { 1212 rc = timer_check_and_block(&Timer); 1213 if (rc) break; 1214 } 1215 1216 if (rc) { 1214 1217 dprintf("timeout for IORB %Fp\n", iorb); 1215 1218 iorb_seterr(iorb, IOERR_ADAPTER_TIMEOUT); 1216 1217 1219 } else if (readl(port_mmio + PORT_SCR_ERR) != 0 || 1218 1220 readl(port_mmio + PORT_TFDATA) & 0x89) { … … 1220 1222 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC); 1221 1223 ahci_reset_port(ai, iorb_unit_port(iorb), 0); 1222 1223 1224 } else { 1224 1225 /* successfully executed command */ … … 1259 1260 u32 tmp; 1260 1261 int rc; 1262 TIMER Timer; 1261 1263 1262 1264 /* verify that command slot 0 is idle */ … … 1277 1279 1278 1280 /* wait until command has completed */ 1279 while (timeout > 0 && (readl(port_mmio + PORT_CMD_ISSUE) & 1)) { 1280 mdelay(10); 1281 timeout -= 10; 1282 } 1283 ddprintf(" done (time left = %d)\n", timeout); 1281 timer_init(&Timer, timeout); 1282 rc = 0; 1283 while (readl(port_mmio + PORT_CMD_ISSUE) & 1) { 1284 rc = timer_check_and_block(&Timer); 1285 if (rc) break; 1286 } 1284 1287 1285 1288 /* check error condition */ 1286 1289 if ((tmp = readl(port_mmio + PORT_SCR_ERR)) != 0) { 1287 1290 dprintf("SERR = 0x%08lx\n", tmp); 1288 timeout = 0;1291 rc = 1; 1289 1292 } 1290 1293 if (((tmp = readl(port_mmio + PORT_TFDATA)) & 0x89) != 0) { 1291 1294 dprintf("TFDATA = 0x%08lx\n", tmp); 1292 timeout = 0;1293 } 1294 1295 if ( timeout <= 0) {1295 rc = 1; 1296 } 1297 1298 if (rc) { 1296 1299 ahci_reset_port(ai, p, 0); 1297 1300 return(-1); -
trunk/src/os2ahci/apm.c
r153 r157 104 104 int p; 105 105 int d; 106 TIMER Timer; 106 107 107 108 if (suspended) return; … … 115 116 for (p = 0; p <= ai->port_max; p++) { 116 117 /* wait until all active commands have completed on this port */ 118 timer_init(&Timer, 250); 117 119 while (ahci_port_busy(ai, p)) { 118 msleep(250);120 if (timer_check_and_block(&Timer)) break; 119 121 } 120 122 -
trunk/src/os2ahci/ata.c
r156 r157 443 443 int check_lvm(IORBH _far *iorb, ULONG sector) 444 444 { 445 ADD_WORKSPACE _far *aws = add_workspace(iorb);445 DLA_Table_Sector *pDLA = (DLA_Table_Sector*)add_workspace(iorb)->buf; 446 446 AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb); 447 447 GEOMETRY _far *geometry = ((IORB_GEOMETRY _far *) iorb)->pGeometry; 448 PDLA_Table_Sector pDLA;449 448 int p = iorb_unit_port(iorb); 450 449 int rc; … … 453 452 AP_SECTOR_28, (u32) sector-1, 454 453 AP_COUNT, (u16) 1, 455 AP_VADDR, (void _far *) aws->buf, 512,454 AP_VADDR, (void _far *) pDLA, 512, 456 455 AP_DEVICE, 0x40, 457 456 AP_END); 458 457 if (rc) return 0; 459 458 460 pDLA = (PDLA_Table_Sector)aws->buf;461 459 ddphex(pDLA, sizeof(DLA_Table_Sector), "DLA sector %d:\n", sector-1); 462 460 463 461 if ((pDLA->DLA_Signature1 == DLA_TABLE_SIGNATURE1) && (pDLA->DLA_Signature2 == DLA_TABLE_SIGNATURE2)) { 464 ddprintf("is_lvm_geometry found at sector %d\n", sector );462 ddprintf("is_lvm_geometry found at sector %d\n", sector-1); 465 463 geometry->TotalCylinders = pDLA->Cylinders; 466 464 geometry->NumHeads = pDLA->Heads_Per_Cylinder; 467 465 geometry->SectorsPerTrack = pDLA->Sectors_Per_Track; 466 geometry->TotalSectors = pDLA->Cylinders * pDLA->Heads_Per_Cylinder * pDLA->Sectors_Per_Track; 468 467 return 1; 469 468 } … … 605 604 if (is_lvm_geometry(iorb)) Method = "LVM"; 606 605 607 if (debug) { 608 printf("Drive geometry: %d cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n", 609 (u16) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack, 610 (u32) (geometry->TotalSectors / 2048), Method); 611 } 606 dprintf("Drive geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n", 607 (u32) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack, 608 (u32) (geometry->TotalSectors / 2048), Method); 612 609 613 610 /* tell interrupt handler that this IORB is complete */ -
trunk/src/os2ahci/init.asm
r155 r157 29 29 PUBLIC _end_of_data ; end of all data (label) 30 30 PUBLIC _end_of_code ; end of all code (label) 31 PUBLIC _udelay ; spin for microseconds 32 EXTRN DOSIODELAYCNT:ABS 31 33 32 34 ; ---------------------------------------------------------------------------- … … 198 200 .386 199 201 202 ; void udelay(u16 microseconds); 203 _udelay PROC NEAR 204 enter 0, 0 205 mov cx, word ptr [bp+4] 206 @OuterLoop: 207 mov ax, DOSIODELAYCNT 208 shl ax, 1 209 @InnerLoop: 210 dec ax 211 jnz short @InnerLoop 212 loop @OuterLoop 213 214 leave 215 ret 216 _udelay ENDP 200 217 201 218 ; Read long value from MMIO address; need to do this here to get real -
trunk/src/os2ahci/libc.c
r156 r157 40 40 /* ------------------------ typedefs and structures ------------------------ */ 41 41 42 #ifdef NOT_USED 42 43 /* mdelay() calibration status */ 43 44 typedef enum { … … 47 48 MD_CALIBRATION_DONE /* calibration complete */ 48 49 } MDCAL; 50 static void _cdecl _far mdelay_timer_callback (ULONG timer_handle, 51 ULONG parm1, 52 ULONG parm2); 53 static int mdelay_cal_end (void); 54 #endif 49 55 50 56 /* -------------------------- function prototypes -------------------------- */ … … 54 60 int base, 55 61 int zero, int flen); 56 static void _cdecl _far mdelay_timer_callback (ULONG timer_handle,57 ULONG parm1,58 ULONG parm2);59 static int mdelay_cal_end (void);60 62 61 63 /* ------------------------ global/static variables ------------------------ */ … … 92 94 }; 93 95 96 #ifdef NOT_USED 94 97 /* delay loop calibration data */ 95 98 volatile MDCAL mdelay_cal_status = 0; /* delay loop calibration status */ 96 99 volatile u32 mdelay_loops_per_ms = 0; /* delay loop counter */ 100 #endif 97 101 98 102 /* very small heap for dynamic memory management */ … … 684 688 } 685 689 690 #ifdef NOT_USED 686 691 /****************************************************************************** 687 692 * Calibrate 'mdelay()' loop. This is done by setting up a 1 second timer … … 764 769 mdelay_cal_status = MD_CALIBRATION_DONE; 765 770 } 766 767 /****************************************************************************** 768 * Sleep specified number of milliseonds. This is implemented by yielding the 769 * CPU until the system timer value indicates we're done. This function can 771 #endif 772 773 /****************************************************************************** 774 * Setup the millisecond timer. This is implemented by blocking (yielding the 775 * CPU) until the system timer value indicates we're done. This function can 770 776 * only be called at task time, or from a context hook. 771 777 * … … 773 779 * can lead to intervals up to 55ms (18.2 timer interrupts per second). 774 780 */ 781 void timer_init(TIMER far *pTimer, u32 Milliseconds) 782 { 783 pTimer->Start = gis->msecs; 784 pTimer->End = pTimer->Start + Milliseconds; 785 } 786 787 /****************************************************************************** 788 * Check the millisecond timer. Block if not done. 789 */ 790 int timer_check_and_block(TIMER far *pTimer) 791 { 792 u32 current; 793 794 current = gis->msecs; 795 if (pTimer->Start < pTimer->End) { 796 if ((current >= pTimer->End) || (current < pTimer->Start)) return 1; 797 } else { 798 if ((current >= pTimer->End) && (current < pTimer->Start)) return 1; 799 } 800 DevHelp_ProcBlock((ULONG)&timer_check_and_block, 1, WAIT_IS_INTERRUPTABLE); 801 return 0; 802 } 803 804 /****************************************************************************** 805 * Sleep specified number of milliseonds. 806 */ 775 807 void msleep(u32 millies) 776 808 { 777 ULONG start; 778 ULONG end; 779 ULONG event_id; 780 781 if (gis == NULL) { 782 /* no global info segment; use mdelay() */ 783 mdelay(millies); 784 return; 785 } 786 787 start = gis->msecs; 788 end = start + millies; 789 event_id = (ULONG)&msleep; 790 791 if (end < start) { 792 /* wrap-around; wait until 'msecs' has wrapped, too */ 793 while (gis->msecs >= start) { 794 DevHelp_ProcBlock(event_id, 1, WAIT_IS_INTERRUPTABLE); 795 } 796 } 797 798 while (gis->msecs <= end) { 799 DevHelp_ProcBlock(event_id, 1, WAIT_IS_INTERRUPTABLE); 800 } 809 TIMER Timer; 810 811 timer_init(&Timer, millies); 812 while (!timer_check_and_block(&Timer)); 801 813 } 802 814 … … 885 897 } 886 898 899 #ifdef NOT_USED 887 900 /****************************************************************************** 888 901 * Timer callback handler for 'mdelay_calibrate()' … … 904 917 return(mdelay_cal_status == MD_CALIBRATION_END); 905 918 } 906 919 #endif -
trunk/src/os2ahci/os2ahci.c
r156 r157 417 417 /* initialization succeeded and we found at least one AHCI adapter */ 418 418 ADD_InitTimer(timer_pool, sizeof(timer_pool)); 419 mdelay_cal();419 //NOT_USED mdelay_cal(); 420 420 421 421 if (DevHelp_RegisterDeviceClass(drv_name, (PFN) add_entry, 0, 1, &add_handle)) { … … 1421 1421 void lock_adapter(AD_INFO *ai) 1422 1422 { 1423 TIMER Timer; 1424 1423 1425 spin_lock(drv_lock); 1424 1426 while (ai->busy) { 1425 1427 spin_unlock(drv_lock); 1426 msleep(250); 1428 timer_init(&Timer, 250); 1429 while (!timer_check_and_block(&Timer)); 1427 1430 spin_lock(drv_lock); 1428 1431 } -
trunk/src/os2ahci/os2ahci.h
r156 r157 283 283 284 284 typedef unsigned int size_t; 285 286 typedef struct { 287 u32 Start; 288 u32 End; 289 } TIMER; 285 290 286 291 /* PCI device information structure; this is used both for scanning and for … … 427 432 extern void _cdecl _far engine_hook (void); 428 433 extern void _cdecl _far asm_krnl_exit (void); 434 extern void _cdecl udelay (u16 microseconds); 429 435 430 436 /* os2ahci.c */ … … 519 525 extern void free (void *ptr); 520 526 extern ULONG virt_to_phys (void _far *ptr); 521 extern void mdelay_cal (void);522 extern void mdelay (u32 millies);527 //NOT_USED extern void mdelay_cal (void); 528 //NOT_USED extern void mdelay (u32 millies); 523 529 extern void msleep (u32 millies); 524 530 extern void panic (char *msg); 525 531 extern int disable (void); 526 532 extern void enable (void); 533 extern void timer_init(TIMER far *pTimer, u32 Milliseconds); 534 extern int timer_check_and_block(TIMER far *pTimer); 527 535 528 536 /* trace.c */
Note:
See TracChangeset
for help on using the changeset viewer.