Date: Sun, 14 Sep 1997 20:06:01 +0300 (IDT) From: Eli Zaretskii To: DJ Delorie cc: djgpp-workers AT delorie DOT com Subject: statfs in 970831 Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk A patch for statfs that makes it work better with CD-ROM drives. diff -c src/libc/compat/sys/vfs/statfs.c~0 src/libc/compat/sys/vfs/statfs.c *** src/libc/compat/sys/vfs/statfs.c~0 Sun Aug 31 21:19:12 1997 --- src/libc/compat/sys/vfs/statfs.c Sat Mar 29 11:48:10 1997 *************** *** 1,12 **** /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - #include #include #include ! #include #include #include #include #include #include int --- 1,14 ---- + /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include ! #include #include + #include #include #include #include + #include #include int *************** *** 28,119 **** } /* For a CD-ROM drive, 213600 gives incorrect info. ! Use CD-ROM-specific calls if they are available. */ regs.x.ax = 0x150b; /* is this drive supported by CD-ROM driver? */ regs.x.cx = drive_number; __dpmi_int(0x2f, ®s); if ((regs.x.flags & 1) == 0 && regs.x.bx == 0xadad && regs.x.ax != 0) { ! int drv_pos; ! ! /* Find this drive's position in the list of CD-ROM drives ! on this system (there might be more than one CD drive!) */ ! regs.x.ax = 0x150d; ! regs.x.es = __tb_segment; ! regs.x.bx = 0; ! __dpmi_int (0x2f, ®s); ! _farsetsel (_dos_ds); ! for (drv_pos = 0; drv_pos <= drive_number; drv_pos++) ! if (_farnspeekb (__tb + drv_pos) == drive_number) ! break; ! if (drv_pos <= drive_number) ! { ! char dev_name[9], *p = dev_name + 7; ! int drv_off, drv_seg, drv_addr; ! /* 2F1501 will return an array of pointers to device driver ! headers for each supported drive. Each array element ! occupies 5 bytes: 1 byte for subunit number and 4 bytes ! for a DWORD address of the device drive header for this drive. */ ! regs.x.ax = 0x1501; regs.x.es = __tb_segment; ! regs.x.bx = 0; __dpmi_int (0x2f, ®s); ! drv_off = _farpeekw (_dos_ds, __tb + drv_pos*5 + 1); ! drv_seg = _farpeekw (_dos_ds, __tb + drv_pos*5 + 3); ! drv_addr = drv_seg * 16 + drv_off; ! ! /* The device name is at offset 0Ah in the device driver header. */ ! dosmemget (drv_addr + 0x0a, 8, dev_name); ! while (p > dev_name && p[-1] == ' ') ! p--; ! *p = '\0'; ! if (dev_name[0]) { ! /* Open the device name and call 214402 to read the info. */ ! int fd = open (dev_name, O_RDONLY | O_BINARY); ! ! if (fd >= 0) ! { ! int i = 2, bsize = 0; ! ! /* First time after the door is closed the IOCTL call ! might fail. Therefore try twice before giving up. */ ! do ! { ! regs.x.ax = 0x4402; ! regs.x.bx = fd & 0xffff; ! regs.x.cx = 2; ! _farpokeb (_dos_ds, __tb, 7); ! _farpokeb (_dos_ds, __tb + 1, 0); ! regs.x.ds = __tb_segment; ! regs.x.dx = 0; ! __dpmi_int (0x21, ®s); ! if ((regs.x.flags & 1) == 0 && regs.x.ax == 2) ! { ! bsize = _farpeekw (_dos_ds, __tb + 2); ! ! regs.x.ax = 0x4402; ! regs.x.bx = fd & 0xffff; ! regs.x.cx = 4; ! _farpokeb (_dos_ds, __tb, 8); ! __dpmi_int (0x21, ®s); ! } ! } while (--i && (regs.x.flags & 1)); ! ! if ((regs.x.flags & 1) == 0 && regs.x.ax == 4) ! { ! regs.x.ax = 1; ! regs.x.cx = bsize; ! regs.x.bx = 0; /* no free space: cannot add data */ ! blocks = _farpeekl (_dos_ds, __tb + 1); ! cdrom_calls_used = 1; ! } ! ! close (fd); ! } } } } --- 30,98 ---- } /* For a CD-ROM drive, 213600 gives incorrect info. ! Use CD-ROM-specific calls if they are available. ! ! Int 2Fh/AX=1510h gives us a way of doing IOCTL with the ! CD-ROM device driver without knowing the name of the ! device (which is defined by the CONFIG.SYS line that ! installs the driver and can therefore be arbitrary). */ regs.x.ax = 0x150b; /* is this drive supported by CD-ROM driver? */ regs.x.cx = drive_number; __dpmi_int(0x2f, ®s); if ((regs.x.flags & 1) == 0 && regs.x.bx == 0xadad && regs.x.ax != 0) { ! unsigned char request_header[0x14]; ! int status, i = 2, bsize = 0; ! /* Construct the request header for the CD-ROM device driver. */ ! memset (request_header, 0, sizeof request_header); ! request_header[0] = sizeof request_header; ! request_header[2] = 3; /* IOCTL READ command */ ! *(unsigned short *)&request_header[0xe] = __tb_offset; ! *(unsigned short *)&request_header[0x10] = __tb_segment; ! request_header[0x12] = 4; /* number of bytes to transfer */ ! ! /* When the disk was just changed, we need to try twice. */ ! do { ! /* Put control block into the transfer buffer. */ ! _farpokeb (_dos_ds, __tb, 7); /* read sector size */ ! _farpokeb (_dos_ds, __tb + 1, 0); /* cooked mode */ ! _farpokew (_dos_ds, __tb + 2, 0); /* zero out the result field */ ! ! /* Put request header into the transfer buffer and call the driver. */ ! dosmemput (request_header, sizeof (request_header), __tb + 4); ! regs.x.ax = 0x1510; ! regs.x.cx = drive_number; regs.x.es = __tb_segment; ! regs.x.bx = __tb_offset + 4; __dpmi_int (0x2f, ®s); ! status = _farpeekw (_dos_ds, __tb + 7); ! bsize = _farpeekw (_dos_ds, __tb + 2); ! } while (--i && (status & 0x800f) == 0x800f); /* disk changed */ ! if (status == 0x100 && _farpeekw (_dos_ds, __tb + 4 + 0x12) == 4) ! { ! request_header[0x12] = 5; /* number of bytes to transfer */ ! /* Put control block into the transfer buffer. */ ! _farpokeb (_dos_ds, __tb, 8); /* read volume size */ ! _farpokel (_dos_ds, __tb + 1, 0); /* zero out the result field */ ! ! /* Put request header into the transfer buffer and call the driver. */ ! dosmemput (request_header, sizeof (request_header), __tb + 5); ! regs.x.ax = 0x1510; ! regs.x.cx = drive_number; ! regs.x.es = __tb_segment; ! regs.x.bx = __tb_offset + 5; ! __dpmi_int (0x2f, ®s); ! if (_farpeekw (_dos_ds, __tb + 8) == 0x100 ! && _farpeekw (_dos_ds, __tb + 5 + 0x12) == 5) { ! regs.x.ax = 1; /* fake: sectors per cluster */ ! regs.x.cx = bsize; ! regs.x.bx = 0; /* no free space: cannot add data to CD-ROM */ ! blocks = _farpeekl (_dos_ds, __tb + 1); ! cdrom_calls_used = 1; } } } *************** *** 172,175 **** } #endif - --- 151,153 ----