diff -u --recursive --new-file ../linux-2.2.2/linux/arch/i386/boot/setup.S ./linux/arch/i386/boot/setup.S --- ../linux-2.2.2/linux/arch/i386/boot/setup.S Sun Nov 29 02:18:54 1998 +++ ./linux/arch/i386/boot/setup.S Thu Mar 4 13:06:58 1999 @@ -30,6 +30,8 @@ ! Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david ! parsons) to avoid loadlin confusion, July 1997 ! +! Collection of BIOS disk info, aeb, Feb 1999 +! #define __ASSEMBLY__ #include @@ -59,13 +61,13 @@ entry start start: - jmp start_of_setup + jmp skip_over_header ! ------------------------ start of header -------------------------------- ! ! SETUP-header, must start at CS:2 (old 0x9020:2) ! .ascii "HdrS" ! Signature for SETUP-header - .word 0x0201 ! Version number of header format + .word 0x0202 ! Version number of header format ! (must be >= 0x0105 ! else old loadlin-1.5 will fail) realmode_swtch: .word 0,0 ! default_switch,SETUPSEG @@ -100,7 +102,7 @@ ! loaded at 0x90000. We will move ourselves ! to 0x90000 then just before jumping into ! the kernel. However, only the loader - ! know how much of data behind us also needs + ! knows how much of data behind us also needs ! to be loaded. code32_start: ! here loaders can put a different ! start address for 32-bit code. @@ -120,7 +122,13 @@ ! end of setup code can be used by setup ! for local heap purposes. ! ------------------------ end of header ---------------------------------- - +skip_over_header: + br start_of_setup ! we need this 2-step jump, because we must + ! have a 2 byte jump at start of the header + .align 4 +disk_data: .space 512 +! ------------------------ end of empty_zero_page data ------------------- +! ------------------------ ( must not exceed 2Kb-512 ) ------------------- start_of_setup: ! Bootlin depends on this being done early mov ax,#0x01500 @@ -292,52 +300,170 @@ call video ! NOTE: we need DS pointing to boot sector +! Try to collect all disk information the BIOS can give us. +! Such information is difficult to interpret: +! We don't know whether hd0, hd1, ... are IDE or SCSI disks. +! Some disks may not be mentioned in the BIOS setup and will +! probably not be seen here. +! So, instead of trying to make sense of this, we make the +! collected information available by ioctl to user space. +! +! Layout collected disk data (where DD stands for disk_data) +! 0x0080-0x008f: hd0 data, from int 41 +! 0x0090-0x009f: hd1 data, from int 46 +! DD[0x000-0x02f]: data following int 41 table, possibly hd1..3 +! DD[0x030-0x0af]: hd0..15 geometry, from int 13, fn 15, 8 +! DD[0x0b0-0x1f8]: hd0..3 Phoenix data, from int 13, fn 41,48 +! Phoenix data has extensive info but takes a lot of space +! For the moment for 4 disks only +! ! Get hd0 data - xor ax,ax ! clear ax + xor ax,ax mov ds,ax lds si,[4*0x41] - mov ax,cs ! aka #SETUPSEG + mov ax,cs ! aka #SETUPSEG sub ax,#DELTA_INITSEG ! aka #INITSEG - push ax + push ax ! push INITSEG mov es,ax mov di,#0x0080 mov cx,#0x10 - push cx cld rep movsb -! Get hd1 data +! Get the following 48 bytes - xor ax,ax ! clear ax + mov ax,cs !aka #SETUPSEG + mov es,ax + mov di,#disk_data + mov cx,#0x30 + rep + movsb + +! Clear the area DD[0x030-0x1f8] + + mov cx,#0x1c8 ! 64+64+4*(66+16) + xor ax,ax + rep + stosb + +! Get hd1 data - note that there may not be a hd1 +get_hd1: + xor ax,ax mov ds,ax lds si,[4*0x46] - pop cx - pop es + pop es ! pop INITSEG mov di,#0x0090 + mov cx,#0x10 rep movsb -! Check that there IS a hd1 :-) +! Get drive parameters + mov ax,cs ! aka #SETUPSEG + mov ds,ax + mov dx,#0x80 + mov bx,#disk_data+0x30 +get_drive: + xor cx,cx ! some buggy BIOSes restore cx,dx + push dx + push bx ! superfluous? mov ax,#0x01500 - mov dl,#0x81 int 0x13 - jc no_disk1 + jc no_such_drive cmp ah,#3 - je is_disk1 -no_disk1: - mov ax,cs ! aka #SETUPSEG - sub ax,#DELTA_INITSEG ! aka #INITSEG - mov es,ax - mov di,#0x0090 - mov cx,#0x10 - xor ax,ax ! clear ax - cld + je drive_ok +no_such_drive: + pop bx + add bx,#8 + jmp next_drive +drive_ok: + pop bx + mov (bx),dx + add bx,#2 + mov (bx),cx + add bx,#2 + pop dx + + push dx + push bx + mov ax,#0x0800 + int 0x13 + jnc drive_still_ok + xor cx,cx ! strange.. + xor dx,dx +drive_still_ok: + pop bx + mov (bx),dx + add bx,#2 + mov (bx),cx + add bx,#2 +next_drive: + pop dx + inc dx + cmp dl,#0x90 ! look at 16 disk drives only + jne get_drive ! (to save space and avoid BIOS bugs) + +! Try extensions following the Phoenix specs + mov dl,#0x80 +get_phoenix: + push dx + push bx + mov ax,#0x4100 + mov bx,#0x55aa + int 0x13 + jc no_extensions + cmp bx,#0xaa55 + jne no_extensions + and cx,#0x1 ! test API bitmap - IBM extensions? + jz no_extensions + pop si + pop dx + mov (si),cx ! store API bitmap + ! earlier we tested for Phoenix extensions with + ! and cx,#0x4 + ! But often extensions are present without being indicated + add si,#2 + +! Phoenix extensions are present (for this disk) + push dx + push si + mov (si),#66 ! Phoenix extensions v3.0 uses 66 bytes + mov ax,#0x4800 + int 0x13 ! Read table into ds:si + jc no_extensions ! strange.. + pop bx + cmp (bx),#30 ! did we get at least 30 bytes? + jb no_fdpe + push bx + push ds + lds si,(bx+26) ! ds:si of the FDPE is stored here + pop es + add bx,#66 + cmp si,#0xffff + je no_fdpe2 + mov di,bx + mov cx,#16 rep - stosb -is_disk1: + movsb +no_fdpe2: + push es + pop ds +no_fdpe1: + pop bx +no_fdpe: + add bx,#82 + pop dx + inc dx + cmp dx,#0x84 ! #0x90 + jne get_phoenix + jmp phoenix_done +no_extensions: + pop bx + pop dx +phoenix_done: + ! check for Micro Channel (MCA) bus mov ax,cs ! aka #SETUPSEG @@ -645,7 +771,7 @@ ! ! but we yet haven't reloaded the CS register, so the default size ! of the target offset still is 16 bit. -! However, using an operant prefix (0x66), the CPU will properly +! However, using an operand prefix (0x66), the CPU will properly ! take our 48 bit far pointer. (INTeL 80386 Programmer's Reference ! Manual, Mixing 16-bit and 32-bit code, page 16-6) db 0x66,0xea ! prefix + jmpi-opcode @@ -755,6 +881,7 @@ ! ! No timeout is used - if this hangs there is something wrong with ! the machine, and we probably couldn't proceed anyway. +! However, on some machines this will hang if no keyboard is present. FIXME empty_8042: call delay in al,#0x64 ! 8042 status port diff -u --recursive --new-file ../linux-2.2.2/linux/arch/i386/kernel/setup.c ./linux/arch/i386/kernel/setup.c --- ../linux-2.2.2/linux/arch/i386/kernel/setup.c Tue Feb 23 12:18:57 1999 +++ ./linux/arch/i386/kernel/setup.c Tue Feb 23 12:19:29 1999 @@ -62,6 +62,7 @@ * Setup options */ struct drive_info_struct { char dummy[32]; } drive_info; +struct more_drive_info_struct { char dummy[512]; } more_drive_info; struct screen_info screen_info; #ifdef CONFIG_APM struct apm_bios_info apm_bios_info; @@ -101,6 +102,7 @@ #define KERNEL_START (*(unsigned long *) (PARAM+0x214)) #define INITRD_START (*(unsigned long *) (PARAM+0x218)) #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) +#define MORE_DRIVE_INFO (*(struct more_drive_info_struct *) (PARAM+0x22c)) #define COMMAND_LINE ((char *) (PARAM+2048)) #define COMMAND_LINE_SIZE 256 @@ -256,6 +258,7 @@ ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); drive_info = DRIVE_INFO; + more_drive_info = MORE_DRIVE_INFO; screen_info = SCREEN_INFO; #ifdef CONFIG_APM apm_bios_info = APM_BIOS_INFO; diff -u --recursive --new-file ../linux-2.2.2/linux/drivers/block/hd.c ./linux/drivers/block/hd.c --- ../linux-2.2.2/linux/drivers/block/hd.c Thu Jan 14 19:31:41 1999 +++ ./linux/drivers/block/hd.c Tue Feb 16 02:58:37 1999 @@ -704,7 +704,7 @@ #ifdef __i386__ if (!NR_HD) { - extern struct drive_info drive_info; + extern struct drive_info_struct drive_info; unsigned char *BIOS = (unsigned char *) &drive_info; int cmos_disks; diff -u --recursive --new-file ../linux-2.2.2/linux/drivers/block/ide-probe.c ./linux/drivers/block/ide-probe.c --- ../linux-2.2.2/linux/drivers/block/ide-probe.c Tue Feb 23 12:18:57 1999 +++ ./linux/drivers/block/ide-probe.c Tue Feb 23 12:19:29 1999 @@ -73,7 +73,7 @@ if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ - bswap ^= 1; /* Vertos drives may still be weird */ + bswap = 0; /* Vertos drives may still be weird */ } ide_fixstring (id->model, sizeof(id->model), bswap); ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); @@ -341,6 +341,34 @@ } } return 1; /* drive was found */ +} + +int hdio_getbios(unsigned long arg) { +#ifdef __i386__ + /* return a lot of random BIOS junk about our disks (may not be IDE) */ + extern struct drive_info_struct drive_info; + extern struct more_drive_info_struct more_drive_info; + + char *userdata = (char *) arg; + char *biosdata = (char *) &drive_info; + char *morebiosdata = (char *) &more_drive_info; + int length_of_user_buffer; + int len = 32 + 512; + + copy_from_user(&length_of_user_buffer, userdata, sizeof(int)); + if (length_of_user_buffer < len) + len = length_of_user_buffer; + copy_to_user(userdata, &len, sizeof(int)); + userdata += sizeof(int); + copy_to_user(userdata, biosdata, (len < 32) ? len : 32); + userdata += 32; + len -= 32; + if (len > 0) + copy_to_user(userdata, morebiosdata, len); + return 0; +#else + return -EINVAL; +#endif } /* diff -u --recursive --new-file ../linux-2.2.2/linux/drivers/block/ide.c ./linux/drivers/block/ide.c --- ../linux-2.2.2/linux/drivers/block/ide.c Fri Jan 15 23:36:20 1999 +++ ./linux/drivers/block/ide.c Mon Feb 22 20:14:09 1999 @@ -2068,6 +2068,10 @@ (unsigned long *) &loc->start)) return -EFAULT; return 0; } + case HDIO_GETBIOS: + { extern int hdio_getbios(unsigned long arg); + return hdio_getbios(arg); + } case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; fsync_dev(inode->i_rdev); @@ -2582,46 +2586,30 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg) { ide_drive_t *drive; - static const byte head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; - const byte *heads = head_vals; + static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; + static const byte ez_head_vals[] = {4, 8, 16, 32, 64, 128, 240, 255, 0}; + const byte *heads; unsigned long tracks; drive = get_info_ptr(i_rdev); if (!drive) return 0; - if (drive->forced_geom) { - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; - return 0; +#if FAKE_FDISK_FOR_EZDRIVE + if (xparm == -1) { + drive->remap_0_to_1 = 1; + printk("[remap 0->1] "); } +#endif /* FAKE_FDISK_FOR_EZDRIVE */ - if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) { - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; + if (drive->forced_geom) + return 0; + + if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) return 0; /* we already have a translation */ - } printk("%s ", msg); - if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) { - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; - return 0; /* small disk: no translation needed */ - } - if (drive->id) { drive->cyl = drive->id->cyls; drive->head = drive->id->heads; @@ -2638,18 +2626,13 @@ drive->bios_head = xparm; drive->bios_cyl = tracks / drive->bios_head; } else { + heads = (xparm == -1) ? ez_head_vals : dm_head_vals; while (drive->bios_cyl >= 1024) { drive->bios_head = *heads; drive->bios_cyl = tracks / drive->bios_head; if (0 == *++heads) break; } -#if FAKE_FDISK_FOR_EZDRIVE - if (xparm == -1) { - drive->remap_0_to_1 = 1; - printk("[remap 0->1] "); - } else -#endif /* FAKE_FDISK_FOR_EZDRIVE */ if (xparm == 1) { drive->sect0 = 63; drive->bios_cyl = (tracks - 1) / drive->bios_head; @@ -2658,12 +2641,6 @@ } drive->part[0].nr_sects = current_capacity(drive); printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect); - /* - * Update the current 3D drive values. - */ - drive->id->cur_cyls = drive->bios_cyl; - drive->id->cur_heads = drive->bios_head; - drive->id->cur_sectors = drive->bios_sect; return 1; } diff -u --recursive --new-file ../linux-2.2.2/linux/drivers/scsi/sd_ioctl.c ./linux/drivers/scsi/sd_ioctl.c --- ../linux-2.2.2/linux/drivers/scsi/sd_ioctl.c Wed Oct 14 20:43:14 1998 +++ ./linux/drivers/scsi/sd_ioctl.c Thu Feb 18 17:35:38 1999 @@ -70,6 +70,10 @@ put_user(diskinfo[2], &loc->cylinders); put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start); return 0; + case HDIO_GETBIOS: /* Get a lot of BIOS junk about disks */ + { extern int hdio_getbios(unsigned long arg); + return hdio_getbios(arg); + } case BLKGETSIZE: /* Return device size */ if (!arg) return -EINVAL; error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); diff -u --recursive --new-file ../linux-2.2.2/linux/fs/devices.c ./linux/fs/devices.c --- ../linux-2.2.2/linux/fs/devices.c Wed Dec 23 20:39:49 1998 +++ ./linux/fs/devices.c Fri Feb 19 23:46:56 1999 @@ -228,7 +228,7 @@ */ int blkdev_open(struct inode * inode, struct file * filp) { - int ret = -ENODEV; + int ret = -ENXIO; filp->f_op = get_blkfops(MAJOR(inode->i_rdev)); if (filp->f_op != NULL){ ret = 0; diff -u --recursive --new-file ../linux-2.2.2/linux/include/linux/hdreg.h ./linux/include/linux/hdreg.h --- ../linux-2.2.2/linux/include/linux/hdreg.h Tue Jan 26 01:04:20 1999 +++ ./linux/include/linux/hdreg.h Wed Mar 3 02:03:25 1999 @@ -129,6 +129,7 @@ #define HDIO_GET_DMA 0x030b /* get use-dma flag */ #define HDIO_GET_NICE 0x030c /* get nice flags */ #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */ +#define HDIO_GETBIOS 0x030e /* get a lot of BIOS junk */ #define HDIO_DRIVE_CMD 0x031f /* execute a special drive command */ /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */