Changeset 137
- Timestamp:
- Apr 8, 2017, 12:27:34 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/bootcode/regular/driveio.asm
r136 r137 1453 1453 1454 1454 1455 1456 ; --------------------------------------------------- 1457 ; Rousseau ## Large drives, (OS/2) geometry and LBA ## 1458 ; --------------------------------------------------- 1459 ; A sector size of 512 bytes is assumed in the below calculations. 1460 ; Note that this scheme changes when the sector size will be 4096 or larger, 1461 ; like with modern drives that do not translate to 512 bytes per sector anymore. 1462 ; These drives will have a capacity above the 2TiB LBA32 boundary. 1463 ; For now, we assume drives <=2TiB with a sector size of 512 bytes. 1464 1465 ; There are a few boundaries that are of importance. 1466 ; Note that these are disk-boundaries and not partition boundaries. 1467 ; Even with a small partition, like <502GiB, OS/2 will use extended geometry on 1468 ; an empty huge disk. 1469 ; These boundaries are (from high to low): 1470 1471 ; (code 5) 1472 ; 2^32 = 4294967296 = 100000000 sectors = 2048 GiB 1473 ; This is the LBA32 2TiB boundary. 1474 ; Everything above it must be addressed using LBA48. 1475 ; OS/2 can currently not address this space above. 1476 1477 ; (code4) 1478 ; 65536*255*255 = 4261478400 = FE010000 sectors ~ 2032 GiB 1479 ; This is the max OS/2 boundary using 255/255 extended geometry. 1480 ; OS/2 can currently not address this space above. 1481 1482 ; (code 3) 1483 ; 2^31 = 2147483648 = 80000000 sectors = 1024 GiB 1484 ; This is the LBA32 1TiB boundary. 1485 ; OS/2 can address this space and will use 255/255 extended geometry. 1486 1487 ; (code 2) 1488 ; 65536*255*127 = 2122383360 = 7E810000 sectors ~ 1012 GiB 1489 ; This is the DANI 1TiB boundary. 1490 ; OS/2 can address this space and will use 255/255 extended geometry. 1491 ; Below this DANI will use 255/127 extended geometry. 1492 ; This matters on where the LVM-sectors are located ! 1493 1494 ; (code 1) 1495 ; 65536*255*63 = 1052835840 = 3EC10000 sectors ~ 502 GiB 1496 ; This is the current OS/2 limit using this geometry because OS/2 can 1497 ; currently not address more than 65536 cylinders. 1498 ; DANI will address space above with 255/127 extended geometry up until 1499 ; the DANI 1TiB boundary (code 2) 1500 1501 ; (code 0) 1502 ; Everything below 65536*255*63 will be addressed using standard geometry. 1503 1504 1505 ; 1506 ; This function will return the following values: 1507 ; 1508 1509 ; 5 = This drive is above the 2^32 LBA32 (2TB) boundary and has more 1510 ; than 4294967296 sectors. 1511 ; LBA48 addressing is needed to access the complete capacity of the drive. 1512 ; OS/2 is currently unable to do so. 1513 1514 ; 4 = This drive is above the 65536*255*255 (4261478400) boundary but below 2^32. 1515 ; This is an OS/2 boundary and OS/2 is not able to access the drive above 1516 ; this boundary. 1517 1518 ; 3 = This drive is above the 2^31 (1TB) boundary and has more than 1519 ; 2147483648 sectors. 1520 ; OS/2 is able to access the drive using it's extended geometry. 1521 ; Both DANIS506 and IBM1S506 will use the 255/255 scheme. 1522 1523 ; 2 = This drive is above the 65536*255*127 (2122383360) boundary but below 2^31. 1524 ; OS/2 is able to access the drive using it's extended geometry. 1525 ; Both DANIS506 and IBM1S506 will use the 255/255 scheme. 1526 1527 ; 1 = This drive is above the 65536*255*63 (1052835840) boundary but 1528 ; below 65536*255*127. 1529 ; OS/2 is able to access the drive using it's extended geometry. 1530 ; Note that DANIS506 will use 255/127 and IBM1S506 will use 255/255 geometry ! 1531 ; Using DANI or IBM influences the location of the LVM info-sectors ! 1532 1533 ; 0 = This drive is below the 65536*255*63 (1052835840) boundary. 1534 ; OS/2 is able to access this drive using the standard 255/63 geometry. 1535 1536 ; So, any return value >0 means OS/2 extended geometry will be used. 1537 ; Value 1 will use 255/127 with DANIS506 but 255/255 with IBM1S506. 1538 ; Values 2 and 3 will use 255/255 on both drivers. 1539 ; You can or with 0x01 and check for 3 in this case. 1540 ; Any value above 3 will be a drive who's capacity cannot be fully used by OS/2 1541 ; The upper limit of 65536*255*255 will be in effect here. 1542 1543 ; Note this function currently handles the boot-drive only ! 1544 ; It should be extended and use dl for the drive-number as a parameter. 1545 ; Because we use this function to get this info in a number of places, 1546 ; all regs and flags except AX are saved and restored. 1547 1548 ; DL contains BIOS disk-number; 80h for first, 81h for second, etc. 1455 ;############################################################################## 1456 ;# There is much information to know about the connected disks. 1457 ;# We also want this information clustered per disk and available before 1458 ;# further disk and partition scanning takes place. 1459 ;# This function gathers such information like INT13, INT13X, MBR, LVM, more. 1460 ;# Especially important is the LVM information, because that contains the 1461 ;# geometry OS/2 uses to access the disk. Other important information is the 1462 ;# presence of valid MBRs, logical partitions and whatnot. 1463 ;# This function gathers such information and stores it in a DISKINFO structure 1464 ;# for which an instance exists for every disk found. 1465 ;############################################################################## 1466 ;# ACTION : Gather disk information and store this in the BSS 1467 ;# ---------------------------------------------------------------------------- 1468 ;# EFFECTS : Modifies DAP structure and the buffers it uses, fills DISKINFO[n] 1469 ;# ---------------------------------------------------------------------------- 1470 ;# IN : DL - BIOS disk number (80h,81h,etc) 1471 ;# ---------------------------------------------------------------------------- 1472 ;# OUT : CF=1 - failure 1473 ;############################################################################## 1549 1474 DriveIO_GatherDiskInfo Proc Near 1550 1475 1551 1476 IFDEF AUX_DEBUG 1552 IF 01477 IF 1 1553 1478 DBG_TEXT_OUT_AUX 'DriveIO_GatherDiskInfo:' 1554 1479 PUSHRF … … 1560 1485 ENDIF 1561 1486 1562 pushf 1563 push bx 1564 push cx 1565 push dx 1566 push si 1567 push di 1487 ; Push all registers we use 1488 pusha 1489 push ds 1568 1490 push es 1569 1491 1570 ; Set ES to CS for buffer clearing1571 push cs1492 ; Make sure ES=DS 1493 push ds 1572 1494 pop es 1573 1495 1574 ; Clear the buffer 1575 ; Also setup the buffer size. 1576 ; Old Phoenix BIOSses require word (flags) at 02 to be zero, 1577 ; so we clear the whole buffer to be sure. 1578 mov cx, i13xbuf_size ; Dynamically calculated by assembler. 1579 mov di, offset [i13xbuf] ; Points to size field. 1580 mov [di],cx ; Setup buffer-size. 1581 inc di 1582 inc di ; Now pointing at actual buffer. 1583 xor ah,ah ; Fill value. 1584 cld ; Direction up. 1585 rep stosb ; Clear buffer. 1586 1587 ; Get the drive parameters 1588 mov ah, 48h ; Get Drive Parameters (extended version) 1589 ;mov dl, 80h ; Drive number 1590 mov si, offset [i13xbuf] ; Buffer for result-info 1591 push dx 1592 int 13h ; Call the BIOS-function 1593 pop dx 1594 1595 ; Do some error-checking 1596 or ah,ah ; AH is zero if no error (ZF=1 if no error) 1597 mov ax,0 ; Setup code for non-huge drive (does not influence ZF) 1598 jz DriveIO_GatherDiskInfo_ok ; Return if error (AL<>0 thus ZF=0) but CY not set, assuming non-huge drive 1599 jnc DriveIO_GatherDiskInfo_ok ; Return if error (CY=1), assuming non-huge drive 1496 ; Check if BIOS disk number is valid 1497 call DriveIO_IsValidHarddisk 1498 jc DriveIO_GatherDiskInfo_error 1499 1500 ; Calculate the entry in the DISKINFO array for this disk 1501 call DriveIO_CalcDiskInfoPointer 1502 1503 ; Save the entry for later recalls 1504 mov bp, bx 1505 1506 ; Store the BIOS disk number in the structure 1507 mov [bx+LocDISKINFO_DiskNum], dl 1508 1509 ; ------------------------------------------------------------------- [ INT13 ] 1510 1511 ; Get BIOS Disk Parameters (legacy method) 1512 mov ah, 08h ; Get Disk Parameters 1513 int 13h ; Call BIOS 1514 1515 ; CF=1 or AH!=0 indicates error 1516 jc DriveIO_GatherDiskInfo_error 1517 test ah, ah 1518 jnz DriveIO_GatherDiskInfo_error 1519 1520 ; Recall DISKINFO entry 1521 mov bx, bp 1522 1523 ; Store SPT (WORD) 1524 xor ah, ah ; Zero extend SPT to 16 bits 1525 mov al, cl ; Hi 2 bits max cyl and max sec 1526 and al, 3fh ; Mask max sec (1-based) 1527 mov [bx+LocDISKINFO_I13_Secs], ax ; Store SPT 1528 1529 ; Store HEADS (WORD) 1530 xor dl, dl ; Zero extend HEADS to 16 bits 1531 xchg dl, dh ; Get max head (0-based) 1532 inc dx ; Head count 1533 mov [bx+LocDISKINFO_I13_Heads], dx ; Store HEADS 1534 1535 ; Store CYLS (WORD) 1536 shr cl, 6 ; Hi 2 bits of max cyl to 1:0 1537 xchg cl, ch ; Max cyl (0-based) 1538 inc cx ; Cyl count 1539 mov [bx+LocDISKINFO_I13_Cyls], cx ; Store CYLS 1540 1541 ; Recall BIOS disk number 1542 mov dl, [bx+LocDISKINFO_DiskNum] 1543 1544 ; ------------------------------------------------------------------ [ INT13X ] 1545 1546 ; Get BIOS Disk Parameters (extended method) 1547 mov si, offset [Scratch] ; Buffer to return disk info 1548 mov ax, 80h ; Size of buffer 1549 mov [si], ax ; Store it in first word 1550 mov ah, 48h ; Get Extended Disk Parameters 1551 int 13h ; Call BIOS 1552 1553 ; CF=1 or AH!=0 indicates error 1554 jc DriveIO_GatherDiskInfo_error 1555 test ah, ah 1556 jnz DriveIO_GatherDiskInfo_error 1557 1558 ; Store flags (WORD) 1559 cld ; Direction up 1560 lodsw ; Buffersize, discard 1561 lodsw ; Flags (CHS valid etc) 1562 mov [bx+LocDISKINFO_I13X_Flags], ax ; Store them 1563 1564 ; Store CYLS (DWORD) 1565 lodsw ; Cyl count low 1566 mov [bx+LocDISKINFO_I13X_Cyls+00h], ax ; Store CYLS low 1567 lodsw ; Cyl count high 1568 mov [bx+LocDISKINFO_I13X_Cyls+02h], ax ; Store CYLS high 1569 1570 ; Store HEADS (DWORD) 1571 lodsw ; Head count low 1572 mov [bx+LocDISKINFO_I13X_Heads+00h], ax ; Store HEADS low 1573 lodsw ; Head count high 1574 mov [bx+LocDISKINFO_I13X_Heads+02h], ax ; Store HEADS high 1575 1576 ; Store SPT (DWORD) 1577 lodsw ; Secs per track low 1578 mov [bx+LocDISKINFO_I13X_Secs+00h], ax ; Store SPT low 1579 lodsw ; Secs per track high 1580 mov [bx+LocDISKINFO_I13X_Secs+02h], ax ; Store SPT high 1581 1582 ; Store total LBA sectors (QWORD) 1583 lea di, [bx+LocDISKINFO_I13X_SecsLBA] 1584 mov cx, 4 1585 rep movsw 1586 1587 ; Store sector size (WORD) 1588 lodsw 1589 mov [bx+LocDISKINFO_I13X_SecSize], ax 1590 1591 ; Store bus name (4 bytes, space padded, v3.0+) 1592 lea si, [Scratch+24h] 1593 lea di, [bx+LocDISKINFO_I13X_HostBus] 1594 movsw 1595 movsw 1596 1597 ; Store interface name (8 bytes, space padded, v3.0+) 1598 lea di, [bx+LocDISKINFO_I13X_Interface] 1599 mov cx, 4 1600 rep movsw 1601 1602 ; Should gather some more INT13X info here, 1603 ; like maybe Advanced Format stuff or so. 1604 ; We'll investigate that at a later time. 1605 1606 ; --------------------------------------------------------------------- [ MBR ] 1607 1608 ; Load the MBR 1609 mov si, offset [TmpSector] 1610 call DriveIO_LoadMBR 1611 1612 ; Store MBR flags (valid sig, partitions present, airboot installed) 1613 mov [bx+LocDISKINFO_MbrFlags], al 1614 1615 ; Recall BIOS disk number 1616 mov dl, [bx+LocDISKINFO_DiskNum] 1617 1618 ; --------------------------------------------------------------------- [ LVM ] 1619 1620 ; Locate the Master LVM sector, if any 1621 call DriveIO_LocateMasterLVMSector 1622 1623 ; Save Master LVM sector LBA high 1624 mov cx, bx 1625 1626 ; Recall DISKINFO entry 1627 mov bx, bp 1628 1629 ; Store Master LVM sector LBA 1630 mov [bx+LocDISKINFO_LVM_MasterLBA+00h], ax 1631 mov [bx+LocDISKINFO_LVM_MasterLBA+02h], cx 1632 1633 ; No Master LVM sector found, so skip storing LVM info for this disk 1634 jnc DriveIO_GatherDiskInfo_no_master_lvm 1635 1636 ; Load the Master LVM sector into [LVMSector] 1637 call DriveIO_LoadMasterLVMSector 1638 1639 ; No valid Master LVM sector, so skip storing LVM info for this disk 1640 jc DriveIO_GatherDiskInfo_no_master_lvm 1641 1642 ; A valid Master LVM sector has been loaded into [LVMSector] 1643 mov si, offset [LVMSector] 1644 1645 ; Get the number of sectors per track (OS/2 geometry) 1646 mov ax, [si+LocLVM_Secs+00h] 1647 mov cx, [si+LocLVM_Secs+02h] 1648 1649 ; Store it 1650 mov [bx+LocDISKINFO_LVM_Secs+00h], ax 1651 mov [bx+LocDISKINFO_LVM_Secs+02h], cx 1652 1653 ; Get the number of heads (OS/2 geometry) 1654 mov ax, [si+LocLVM_Heads+00h] 1655 mov cx, [si+LocLVM_Heads+02h] 1656 1657 ; Store it 1658 mov [bx+LocDISKINFO_LVM_Heads+00h], ax 1659 mov [bx+LocDISKINFO_LVM_Heads+02h], cx 1660 1661 ; Should gather some more LVM info here, 1662 ; like OS/2 extended geometry and other flags. 1663 ; We'll implement that at a later time. 1664 1665 DriveIO_GatherDiskInfo_no_master_lvm: 1666 1667 ; When no Master LVM sector was found, 1668 ; the LVM info in the DISKINFO structure for the disk 1669 ; will be ZERO because the area was cleared in PRECRAP. 1670 1671 ; Indicate success 1672 clc 1673 1600 1674 jmp DriveIO_GatherDiskInfo_ret 1601 1675 1602 1603 DriveIO_GatherDiskInfo_ok: 1604 1605 ; 1606 ; Store the drive geometry 1607 ; 1608 1609 mov si, offset i13xbuf 1610 1611 xor dh,dh 1612 and dl,01111111b 1613 shl dx,1 1614 shl dx,1 1615 1616 ; Store number of cylinders on disk 1617 mov bx, offset BIOS_Cyls 1618 add bx,dx 1619 mov ax,[si+04h] 1620 1621 mov word ptr [bx+00],ax 1622 mov ax,[si+06] 1623 mov word ptr [bx+02],ax 1624 1625 ; Store number of heads per cylinder 1626 mov bx, offset BIOS_Heads 1627 add bx,dx 1628 mov ax,[si+08h] 1629 mov word ptr [bx+00],ax 1630 mov ax,[si+0ah] 1631 mov word ptr [bx+02],ax 1632 1633 ; Store number of sectors per track 1634 mov bx, offset BIOS_Secs 1635 add bx,dx 1636 mov ax,[si+0ch] 1637 mov word ptr [bx+00],ax 1638 1639 ; Update first byte of translation-table to conform to BIOS SPT 1640 ; rousseau.comment.201610122010 1641 ; Very bad !! 1642 ; This table is global and the instruction below would change the 1643 ; first (last checked) 'well known' SPT value to the SPT value of 1644 ; the last disk scanned. This goes wrong when the last disk scanned 1645 ; has a SPT <63, which is often the case when an USB stick is present 1646 ; when AirBoot starts. 1647 ;~ mov byte ptr [secs_per_track_table], al 1648 1649 mov ax,[si+0eh] 1650 mov word ptr [bx+02],ax 1651 1652 ; Store total secs 1653 mov bx, offset [BIOS_TotalSecs] 1654 add bx,dx 1655 add bx,dx 1656 mov ax,[si+10h] 1657 1658 mov word ptr [bx+00],ax 1659 mov ax,[si+12h] 1660 mov word ptr [bx+02],ax 1661 mov ax,[si+14h] 1662 mov word ptr [bx+04],ax 1663 mov ax,[si+18h] 1664 mov word ptr [bx+06],ax 1665 1666 ; Store number of bytes per sector 1667 mov bx, offset [BIOS_Bytes] 1668 add bx,dx 1669 mov ax,[si+18h] 1670 mov [bx],ax 1671 1672 1673 ; 1674 ; See of it's a huge drive of not 1675 ; 1676 1677 ; Drive is larger than 2TiB 1678 mov ax,5 ; Drive code (5) 1679 mov bx, [si+14h] ; Low word of high dword of sector-count 1680 or bx, [si+16h] ; High word of high dword of sector-count 1681 jnz DriveIO_GatherDiskInfo_ret ; If non-zero we have a drive with >2^32 sectors and thus LBA48 addressing 1682 1683 ; Drive is larger than max OS/2 capacity 1684 dec ax ; Drive code (4) 1685 mov bx, [si+12h] ; High word of low dword of sector-count 1686 cmp bx, 0fe01h ; Boundary 1687 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary, 1688 ; we have a drive larger than to 65536*255*255 = FE010000 sectors 1689 1690 ; Drive can be completely utilized by OS/2 1691 dec ax ; Drive code (3) 1692 cmp bx, 8000h ; Boundary 1693 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary, 1694 ; we have a drive larger than 2^31 sectors but smaller than 65536*255*255 1695 1696 ; This is the small area between DANI 1TiB and LBA 1TiB 1697 dec ax ; Drive code (2) 1698 cmp bx, 7e81h ; Boundary 1699 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary, 1700 ; we have a drive larger than 65536*255*127 but <65536*255*255 1701 ; DANIS506.ADD will use 255/255 extended geometry 1702 1703 ; DANI will use 255/127 in this area, this could impact the location of LVM-sectors ! (last sec on track) 1704 dec ax ; Drive code (1) 1705 cmp bx, 3ec1h ; Boundary 1706 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary, 1707 ; we have a drive larger than 65536*255*63 sectors (OS/2 502GiB Limit!) 1708 ; DANIS506.ADD will use 255/127 extended geometry ! 1709 ; IBM1S506.ADD will use 255/255 extended geometry ! 1710 1711 ; We have a drive that can be addressed using standard 255/63 geometry 1712 dec ax ; Drive code (0) 1713 ; We have a drive smaller than 65536*255*63 = 3EC10000 sectors 1714 1676 DriveIO_GatherDiskInfo_error: 1677 stc 1715 1678 DriveIO_GatherDiskInfo_ret: 1679 1680 1681 IFDEF AUX_DEBUG 1682 IF 1 1683 DBG_TEXT_OUT_AUX '[DISKINFO]' 1684 PUSHRF 1685 call DEBUG_DumpRegisters 1686 ;~ call AuxIO_DumpParagraph 1687 ;~ call AuxIO_TeletypeNL 1688 mov si, bp 1689 mov cx, 4 1690 @@: 1691 call AuxIO_DumpParagraph 1692 call AuxIO_TeletypeNL 1693 add si, 16 1694 loop @B 1695 mov si, offset [Scratch] 1696 mov cx, 4 1697 @@: 1698 call AuxIO_DumpParagraph 1699 call AuxIO_TeletypeNL 1700 add si, 16 1701 loop @B 1702 mov si, offset [LVMSector] 1703 mov cx, 7 1704 @@: 1705 call AuxIO_DumpParagraph 1706 call AuxIO_TeletypeNL 1707 add si, 16 1708 loop @B 1709 POPRF 1710 ENDIF 1711 ENDIF 1712 1713 ; Restore registers 1716 1714 pop es 1717 pop di 1718 pop si 1719 pop dx 1720 pop cx 1721 pop bx 1722 1723 mov byte ptr [CurIO_UseExtension],1 1724 1725 popf 1715 pop ds 1716 popa 1717 1726 1718 ret 1727 1719 DriveIO_GatherDiskInfo EndP … … 1764 1756 1765 1757 ; Values for sectors per track table corresponding to DriveIO_IsHugeDrive return value. 1766 secs_per_track_table db 63,127,255,255,255,2551758 ;~ secs_per_track_table db 63,127,255,255,255,255 1767 1759 1768 1760 ;~ db_lmlvm db 'Load Master LVM -- disk: ',0
Note:
See TracChangeset
for help on using the changeset viewer.