MEMDISK: Try for better EDD compliance
authorH. Peter Anvin <hpa@zytor.com>
Mon, 9 Jul 2007 04:46:58 +0000 (21:46 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Mon, 9 Jul 2007 04:46:58 +0000 (21:46 -0700)
memdisk/memdisk.asm
memdisk/setup.c

index 90779cb..fc46e84 100644 (file)
@@ -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
index 553c446..bacaba4 100644 (file)
@@ -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)