From 056069afebceef2b84746b2b9db7063bfa67da9f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 8 Jul 2007 21:46:58 -0700 Subject: [PATCH] MEMDISK: Try for better EDD compliance --- memdisk/memdisk.asm | 84 ++++++++++++++++++++++++++++++----------------------- memdisk/setup.c | 29 ++++++++++++++++++ 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm index 90779cb..fc46e84 100644 --- a/memdisk/memdisk.asm +++ b/memdisk/memdisk.asm @@ -275,6 +275,8 @@ CheckIfReady: ; These are always-successful noop functions Recalibrate: InitWithParms: DetectChange: +EDDDetectChange: +EDDLock: SetMode: success: xor ax,ax ; Always successful @@ -335,8 +337,9 @@ EDDPresence: cmp P_BX,55AAh jne Invalid mov P_BX,0AA55h ; EDD signature - mov P_AX,02100h ; EDD 1.1 - mov P_CX,0001h ; Fixed disk access subset + mov P_AX,03000h ; EDD 3.0 + mov P_CX,0003h ; Bit 0 - Fixed disk access subset + ; Bit 1 - Locking and ejecting subset pop ax ; Drop return address xor ax,ax ; Success jmp DoneWeird ; Success, but AH != 0, sigh... @@ -372,23 +375,22 @@ EDDGetParms: mov es,P_DS mov di,P_SI - mov cx,30 ; Length of our DPT - cmp [es:di],cx - jae .oksize + mov si,EDD_DPT - mov cx,26 - cmp [es:di],cx + lodsw ; Length of our DPT + mov cx,[es:di] + cmp cx,26 ; Minimum size jb .overrun + cmp cx,ax + jb .oksize + mov cx,ax .oksize: - mov [si],cx - - ; This should be done by the installer... - mov eax,[DiskSize] - mov [si+16],eax - - mov si,EDD_DPT + mov ax,cx + stosw + dec cx + dec cx rep movsb xor ax,ax @@ -466,15 +468,17 @@ edd_setup_regs: movzx edi,word [es:si+6] ; Segment shl edi,4 add esi,edi - jmp .got_address .linear_address: - cmp dx,24 ; Must be large enough to hold linear address + cmp dx,24 ; Must be large enough to hold + ; linear address jb .baddapa - cmp dword [es:si+20],0 ; > 4 GB addresses not supported - jne .overrun + cmp dword [es:si+20],0 ; > 4 GB addresses not supported + mov ax,0900h ; "Data boundary error" - bogus, but + ; no really better code available + jne .error mov esi,[es:si+16] @@ -503,12 +507,18 @@ edd_setup_regs: ret .overrun: + mov ax,0200h ; "Address mark not found" = + ; LBA beyond end of disk +.error: and word [es:si+2],0 ; No sectors transferred - mov ax,0200h pop es pop ax ret +EDDEject: + mov ax,0B200h ; Volume Not Removable + ret + %endif ; EDD @@ -863,29 +873,16 @@ Int13Funcs dw Reset ; 00h - RESET dw EDDRead ; 42h - EDD READ dw EDDWrite ; 43h - EDD WRITE dw EDDVerify ; 44h - EDD VERIFY - dw Invalid ; 45h - EDD LOCK/UNLOCK MEDIA - dw Invalid ; 46h - EDD EJECT + dw EDDLock ; 45h - EDD LOCK/UNLOCK MEDIA + dw EDDEject ; 46h - EDD EJECT dw EDDSeek ; 47h - EDD SEEK dw EDDGetParms ; 48h - EDD GET PARAMETERS + dw EDDDetectChange ; 49h - EDD MEDIA CHANGE STATUS %endif Int13FuncsEnd equ $ Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1 -%if EDD -EDD_DPT: -.length dw 30 - ; Bit 0 - DMA boundaries handled transparently - ; Bit 3 - Device supports write verify -.info dw 0009h -.cylinders dd 0 ; No physical geometry -.heads dd 0 ; No physical geometry -.sectors dd 0 ; No physical geometry -.totalsize dd 0, 0 ; Total number of sectors -.bytespersec dw SECTORSIZE -.eddtable dw -1, -1 ; Invalid EDD table - -%endif alignb 8, db 0 Shaker dw ShakerEnd-$ @@ -902,7 +899,6 @@ ShakerEnd equ $ alignb 8, db 0 - Mover dd 0, 0, 0, 0 ; Must be zero dw 0ffffh ; 64 K segment size Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy @@ -955,9 +951,23 @@ MyStack dw 0 ; Offset of stack StatusPtr dw 0 ; Where to save status (zeroseg ptr) DPT times 16 db 0 ; BIOS parameter table pointer (floppies) +%if EDD +EDD_DPT: +.length dw 30 +.info dw 0029h + ; Bit 0 - DMA boundaries handled transparently + ; Bit 3 - Device supports write verify + ; Bit 5 - Media is lockable +.cylinders dd 0 ; Filled in by installer +.heads dd 0 ; Filled in by installer +.sectors dd 0 ; Filled in by installer +.totalsize dd 0, 0 ; Filled in by installer +.bytespersec dw SECTORSIZE +.eddtable dw -1, -1 ; Invalid DPTE pointer - ; End patch area +%endif + ; End patch area Stack dd 0 ; Saved SS:ESP on invocation dw 0 SavedAX dw 0 ; AX saved on invocation diff --git a/memdisk/setup.c b/memdisk/setup.c index 553c446..bacaba4 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -60,6 +60,18 @@ typedef union { } fd; } dpt_t; +/* EDD disk parameter table */ +struct edd_dpt { + uint16_t len; /* Length of table */ + uint16_t flags; /* Information flags */ + uint32_t c; /* Physical cylinders (count!) */ + uint32_t h; /* Physical heads (count!) */ + uint32_t s; /* Physical sectors/track (count!) */ + uint64_t sectors; /* Total sectors */ + uint16_t bytespersec; /* Bytes/sector */ + uint16_t dpte_off, dpte_seg; /* DPTE pointer */ +}; + struct patch_area { uint32_t diskbuf; uint32_t disksize; @@ -97,6 +109,7 @@ struct patch_area { uint16_t statusptr; dpt_t dpt; + struct edd_dpt edd_dpt; }; /* This is the header in the boot sector/setup area */ @@ -675,6 +688,22 @@ void setup(syscall_t cs_syscall, void *cs_bounce) pptr->dpt.fd.old_fd_dpt = rdz_32(BIOS_INT1E); } + /* Set up an EDD drive parameter table */ + pptr->edd_dpt.sectors = geometry->sectors; + /* The EDD spec has this as <= 15482880 sectors (1024x240x63); + this seems to make very little sense. Try for something saner. */ + if (geometry->c <= 1024 && geometry->h <= 255 && geometry->s <= 63) { + pptr->edd_dpt.c = geometry->c; + pptr->edd_dpt.h = geometry->h; + pptr->edd_dpt.s = geometry->s; + pptr->edd_dpt.flags |= 0x0002; /* Geometry valid */ + } + if (!(geometry->driveno & 0x80)) { + /* Floppy drive. Mark it as a removable device with + media change notification; media is present. */ + pptr->edd_dpt.flags |= 0x0014; + } + /* The size is given by hptr->total_size plus the size of the E820 map -- 12 bytes per range; we may need as many as 2 additional ranges (each insertrange() can worst-case turn 1 area into 3) -- 2.7.4