Jump to content

Detecting hard/cd drives from DOS?


King_V

Recommended Posts

All,

Well, put my project on hold a bit before, but now I'm getting back into it.

I want to essentially create a Win98Lite boot CD of sorts.

However, what I've been searching for on the web and can't quite get a handle on how to do, is some method that will give me the following:

1) List of hard drives on the system (or the last hard drive) that are NOT cd drives.

2) List of CD drives on the system.

Anyone know how this can be done? I've found a couple of batch file programs that are supposed to be able to show all the drives that exist, but they don't seem to work reliably.

Link to comment
Share on other sites


Use the BIOS int 13 disk services. There are several that can be used, but this one comes to mind:

INT 13 - DISK - GET DISK TYPE (XT 1986/1/10 or later,XT286,AT,PS)

AH = 15h

DL = drive number (bit 7 set for hard disk)

(AL = FFh, CX = FFFFh, see Note)

Return: CF clear if successful

AH = type code

00h no such drive

(SpeedStor) AL = 03h hard disk

CX:DX = number of 512-byte sectors

01h floppy without change-line support

02h floppy (or other removable drive) with change-line support

03h hard disk

CX:DX = number of 512-byte sectors

CF set on error

Loop through from drive 80 onwards, this essentially scans for valid drives. Once a drive is found, it can be determined to be removable or fixed with another function.

The byte at 0040:0075 is also "number of fixed disk drives", according to the IBM PC AT Technical Reference Manual.

Another alternative is to check for drives via hardware I/O through the ports starting at 1F0 (primary IDE controller) and 170 (secondary IDE controller)

Link to comment
Share on other sites

Another alternative is to check for drives via hardware I/O through the ports starting at 1F0 (primary IDE controller) and 170 (secondary IDE controller)

That method seems to yield the best results (including an

ASCII model name) - even on older computers where the

BIOS is incapable of detecting or supporting the drive.

I copied and pasted a chunk below from an IDE document

I didn't know I had.

If you have SCSI like me, the simple method is to load an

ASPI driver from CONFIG.SYS. Both Adaptec and LSI drivers

will scan the bus and list all devices by default. The hard

but more interesting way is to program the SCSI host

adapter card directly - get the data sheet/manual first.

(Also, if you ever wondered why a proper SCSI driver

consumes less CPU, the manual should be enlightening.)

LSI53C1010 - PCI to Dual-Channel Ultra160 SCSI Controller

Controller technical manual

IDE doc quote follows...

5. Register Address Decoding

The host addresses the drive with programmed I/O. Host address lines A0, A1,

A2, chip select CS1FX- and CS3FX-, IOR- and IOW- address the disk registers.

Host address lines A3...A9 generate the two chip selects: CS1FX- and CS3FX-.

Chip select CS1FX- accesses the eight hard disk Command Block Registers.

Chip select CS3FX- is valid during 8 bit transfers to/from the Control Block

registers alternate status and Device Control, and drive address.

The drive selects the primary or alternate command block addresses using

address bit A7.

(Note: What the above sentence means is that there is a provision for a

primary host adapter at I/O address 1FX/3FX and a secondary host adapter at

I/O adress 17X/37X. Each host adapter can have up to two hard drives

MASTER/SLAVED off it).

See below for a graphical explanation:

HEX BINARY DESCRIPTION

1FX 0001 1111 XXXX Primary Command Registers

3FX 0011 1111 XXXX Primary Control Registers

17X 0001 0111 XXXX Alternate Command Registers

37X 0011 0111 XXXX Alternate Control Registers

^

|

+--- Address bit A7

X means "don't care" i.e. X can be 0h, 1h, 2h, ..., Dh, Eh, Fh or 0b, 1b).

Data bus lines D8...D15 are valid only when IOCS16- is active and the drive

is transferring data. The transfer of ECC information occurs only on data

bus lines D0...D7 and data bus lines D8...D15 are invalid during such

transfer.

7. I/O Port Functions

+----+------+------+---+---+---+----------------+---------------+

|Addr|-CS1FX|-CS3FX|SA2|SA1|SA0| Read (-IOR) | Write (-IOW) |

+----+------+------+---+---+---+----------------+---------------+-----------+

| | 0 | 0 | X | X | X | ILLEGAL | ILLEGAL | <--+ |

| | 1 | 1 | X | X | X | High Impedance | Not Used | Control |

|3FX | 1 | 0 | 0 | X | X | High Impedance | Not Used | Block |

|3FX | 1 | 0 | 1 | 0 | X | High Impedance | Not Used | Registers |

|3F6 | 1 | 0 | 1 | 1 | 0 | Altern Status | Device Control| | |

|3F7 | 1 | 0 | 1 | 1 | 1 | Drive Address | Not Used | <--+ |

+----+------+------+---+---+---+----------------+---------------+-----------+

|1F0 | 0 | 1 | 0 | 0 | 0 | Data Port | Data Port | <--+ |

|1F1 | 0 | 1 | 0 | 0 | 1 | Error Register | Precomp | | |

|1F2 | 0 | 1 | 0 | 1 | 0 | Sector Count | Sector Count | Command |

|1F3 | 0 | 1 | 0 | 1 | 1 | Sector Number | Sector Number | Block |

|1F4 | 0 | 1 | 1 | 0 | 0 | Cylinder Low | Cylinder Low | Registers |

|1F5 | 0 | 1 | 1 | 0 | 1 | Cylinder High | Cylinder High | | |

|1F6 | 0 | 1 | 1 | 1 | 0 | Drive / Head | Drive / Head | | |

|1F7 | 0 | 1 | 1 | 1 | 1 | Status | Command | <--+ |

+----+------+------+---+---+---+----------------+---------------+-----------+

At power-up or after reset, the Command Block Registers are initialized to

the following values:

REGISTER VALUE

1F1 Error : 01

1F2 Sector Count : 01

1F3 Sector Number : 01

1F4 Cylinder Low : 00

1F5 Cylinder High : 00

1F6 Drive / Head : 00

------------------------------------------------------------------------

8. Register Descriptions

1F0: Read/Write: DATA PORT REGISTER

All data transferred between the device data buffer and the host passes

through this register. Also, the port to which the sector table is

transferred during execution of the Format command. Transfers of ECC

bytes during the execution of Read/Write Long commands are 8 bit

transfers.

1F1: Read: ERROR REGISTER

Contains status information about the last command executed by the

drive. The contents of this register are valid only when the error bit

(ERR) in the Status Register is set, except at drive power-up or at the

completion of the drive's internal diagnostics, when the register

contains a status code. When the error bit (ERR) is set, Error Register

bits are interpreted as such:

+-----+--------+-------------------------------------------------------------+

| BIT | Mnemon | Description |

+-----+--------+-------------------------------------------------------------+

| 7 | BBK | Bad block mark detected in the requested sector's ID field |

| 6 | UNC | Uncorrectable data error encountered |

| 5 | | Not used |

| 4 | IDNF | Requested sector's ID field not found |

| 3 | | Not used |

| 2 | ABRT | Command aborted due to drive status error or invalid command|

| 1 | TK0NF | Track 0 not found during execution of Recalibrate command |

| 0 | AMNF | Data address mark not found after correct ID field found |

+-----+--------+-------------------------------------------------------------+

1F1: Write: WRITE PRECOMPENSATION

The drive ignores the write precompensation value passed by the host.

1F2: Read/Write: SECTOR COUNT REGISTER

Defines the number of sectors of data to be transferred across the host

bus, for the subsequent command. If the value in this register is zero,

the sector count is 256 sectors. If the command executes successfully,

the value in this register at command completion is zero. As each

sector is transferred, the Sector Count register is decremented by one

to reflect the number of sectors remaining to be transferred. If the

command execution is not successful, this register contains the number

of sectors that must be transferred to complete the original request.

1F3: Read/Write: SECTOR NUMBER REGISTER

Contains the ID number of the first sector to be accessed by the

subsequent command. The sector can be from one to the maximum number of

sectors per track. See the command description for additional

information about the contents of the Sector Number Register following

command completion whether successful or unsuccessful.

1F4: Read/Write: CYLINDER LOW REGISTER

Contains the eight low order bits of the starting cylinder address for

any disk access. On multiple sector transfers that cross cylinder

boundaries, this register is updated at the end of the command to

reflect the current cylinder number. The least significant bits of the

cylinder address are loaded into the cylinder low register.

1F5: Read/Write: CYLINDER HIGH REGISTER

Contains the eight high order bits of the starting cylinder address for

any disk access. On multiple sector transfers that cross cylinder

boundaries, this register is updated at hte end of the command to

reflect the current cylinder number. The most significant bits of the

cylinder address are loaded into the cylinder high register.

1F6: Read/Write: DRIVE/HEAD REGISTER

Contains the drive ID number and its head number for any disk access.

The contents of the Drive/Head Register are defined on execution of the

Initialize Drive Parameters command. The bits are defined as follows:

+-----+----------+---------------------------------------------------------+

| BIT | Mnemonic | Description |

+-----+----------+---------------------------------------------------------+

| 7 | Reserved | Always one. |

| 6 | Reserved | Always zero. |

| 5 | Reserved | Always one. |

| 4 | DRV | 0 to select primary drive, 1 to select secondary drive. |

| 3 | HS3 | MSB of head number. |

| 2 | HS2 | |

| 1 | HS1 | |

| 0 | HS0 | LSB of head number. |

+-----+----------+---------------------------------------------------------+

Upon command completion this register is updated to refplect the head

number currently selected.

1F7: Read: STATUS REGISTER

Contains information about the status of the drive and controller. The

contents of this register are updated at the completion of each

command. When the busy bit is set, no other bits in the Command Block

Registers are valid. When the busy bit is not set, the information in

the Status Register and Command Block Registers is valid.

+-----+----------+----------------------------------------------------------+

| BIT | Mnemonic | Description |

+-----+----------+----------------------------------------------------------+

| 7 | BUSY | Busy bit. Set by the controller logic of the drive when |

| | | ever the drive has access to and the host is locked out |

| | | of the Command Block Registers. Set under the following |

| | | conditions: |

| | | o Within 400 nsec after the negation of RESET or after |

| | | SRST is set in the Device Control Register. After a |

| | | reset it is recomended that BUSY be set no more than |

| | | 30 seconds. |

| | | o Within 400 nsec of a host write to the Command |

| | | Register with a Recalibrate, Read Long, Read Buffer, |

| | | Read, Read Verify, Initialize Drive Parameters, Seek |

| | | Identify Drive, or Execute Drive Diagnostic command. |

| | | o Within 5 microseconds following the transfer of 512 |

| | | bytes of data during the execution of a Write, Write |

| | | Buffer or Format Track command; or 512 bytes of data |

| | | and the appropriate number of ECC bytes during the |

| | | execution of a Write Long command. |

| | | When BUSY is set no Command Block Register can be |

| | | written too and a read of any Command Block Register |

| | | returns the contents of the Status Register. |

| | | |

| 6 | DRDY | Drive Ready bit. Indicates that the drive is ready to |

| | | accept commands. When and error occurs, this bit stays |

| | | unchanged until the host reads the Status Register then |

| | | again indicates that hte drive is ready. On power up, |

| | | this bit should be cleared and should remain cleared |

| | | until the drive is up to speed and ready to accept a |

| | | command. |

| | | |

| 5 | DWF | Drive Write Fault bit. When an error occurs, this bit |

| | | remains unchanged until the host reads the Status |

| | | Register, then again indicates the current write fault |

| | | status. |

| | | |

| 4 | DSC | Drive Seek Complete bit. This bit is set when a seek |

| | | operation is complete and the heads are settled over a |

| | | track. When an error occurs, this bit remains unchanged |

| | | until the host reads the Status Register, then again it |

| | | indicates the current seek complete status. |

| | | |

| 3 | DRQ | Data Request bit. When set it indicates that the drive |

| | | is ready to transfer a word or byte of data between the |

| | | host and the data port. |

| | | |

| 2 | CORR | Corrected Data bit. When a correctable data error has |

| | | been encountered and the data has been corrected, this |

| | | bit is set. This condition does not terminate a multi |

| | | sector read operation. |

| | | |

| 1 | INDEX | Index bit. Set when the index mark is detected once per |

| | | disk revolution. |

| | | |

| 0 | ERROR | Error bit. When set indicates that the previous command |

| | | ended in an error. The other bits in the Error Register |

| | | and Status Register contain additional information about |

| | | the cause of the error. |

+-----+----------+----------------------------------------------------------+

1F7: Write: COMMAND REGISTER

When the host request a command it is transferred to the hard drive

through an eight bit code written to the command register. As soon as

the drive receives a command in its command register, it begins

execution of the command. The following table lists the commands in

alphabetical order and the parameters for each executable command:

+--------+---------------------------------+-----------------+

| Command| Command Description | Parameters Used |

| Code | | PC SC SN CY DH |

+--------+---------------------------------+-----------------+

| 98h @ | Check Power Mode | V D |

| E5h @ | Check Power Mode (same as 98h) | V D |

| 90h | Execute Drive Diagnostic | D+ |

| 50h | Format Track | V V |

| ECh @ | Identify Drive | D |

| 97h @ | Idle | V D |

| E3h @ | Idle (same as 97h) | V D |

| 95h @ | Idle Immediate | D |

| E1h @ | Idle Immadiate (same as 95h) | D |

| 91h | Initialize Drive Parameters | V V |

| E4h @ | Read Buffer | D |

| C8h @ | Read DMA With Retry | >> Unknown << |

| C9h @ | Read DMA | >> Unknown << |

| C4h @ | Read Multiple | V V V V |

| 20h | Read Sectors With Retry | V V V V |

| 21h | Read Sectors | V V V V |

| 22h | Read Long With Retry | V V V V |

| 23h | Read Long | V V V V |

| 40h | Read Verify Sectors With Retry | V V V V |

| 41h | Read Verify Sectors | V V V V |

| 1Xh | Recalibrate | D |

| 7Xh | Seek | V V |

| EFh @ | Set Features | V D |

| C6h @ | Set Multiple Mode | V D |

| 99h @ | Set Sleep Mode | D |

| E6h @ | Set Sleep Mode (same as 99h) | D |

| 96h @ | Standby | V D |

| E2h @ | Standby (same as 96h) | V D |

| 94h @ | Standby Immediate | D |

| E0h @ | Standby Immediate (same as 94h) | D |

| 8Xh | Vendor Unique | >> Unknown << |

| 9Ah | Vendor Unique | >> Unknown << |

| C0h | Vendor Unique | >> Unknown << |

| C1h | Vendor Unique | >> Unknown << |

| C2h | Vendor Unique | >> Unknown << |

| C3h | Vendor Unique | >> Unknown << |

| F5h | Vendor Unique | >> Unknown << |

| F6h | Vendor Unique | >> Unknown << |

| F7h | Vendor Unique | >> Unknown << |

| F8h | Vendor Unique | >> Unknown << |

| F9h | Vendor Unique | >> Unknown << |

| FAh | Vendor Unique | >> Unknown << |

| FBh | Vendor Unique | >> Unknown << |

| FCh | Vendor Unique | >> Unknown << |

| FDh | Vendor Unique | >> Unknown << |

| FEh | Vendor Unique | >> Unknown << |

| FFh | Vendor Unique | >> Unknown << |

| E8h @ | Write Buffer | D |

| CAh @ | Write DMA With Retry | >> Unknown << |

| CBh @ | Write DMA | >> Unknown << |

| C5h @ | Write Multiple | V V V V |

| E9h @ | Write Same | >> Unknown << |

| 30h | Write Sectors With Retry | V V V V |

| 31h | Write Sectors | V V V V |

| 32h | Write Long With Retry | V V V V |

| 33h | Write Long | V V V V |

| 3Ch @ | Write Verify | V V V V |

+--------+---------------------------------+-----------------+

KEY FOR SYMBOLS IN ABOVE TABLE:

PC Register 1F1: Write Precompensation

SC Register 1F2: Sector Count

SN Register 1F3: Sector Number

CY Register 1F4+1F5: Cylinder low + high

DH Register 1F6: Drive / Head

@ These commands are optional and may not be supported by some drives.

D Only DRIVE parameter is valid, HEAD parameter is ignored.

D+ Both drives execute this command regardless of the DRIVE parameter.

V Indicates that the register contains a valid paramterer.

Commands with >> Unknown << Parameters are not described in this

document.

If a parameter is blank, then the command does not require the contents

of that register.

3F6: Read: Alternate Status Register

Contains the same information as the Status Register in the Command

Block. Reading the Alternate Status Register does not imply an

interrupt acknowledge from the host or clear a pending interrupt. See

the description of the Status Register above for a definition of bits

in this register.

3F6: Write: Device Control Register

The bits in the Device Control Register are lister in the table below:

+-----+----------+----------------------------------------------------------+

| BIT | Mnemonic | Description |

+-----+----------+----------------------------------------------------------+

| 7 | Reserved | |

| 6 | Reserved | |

| 5 | Reserved | |

| 4 | Reserved | |

| 3 | 1 | Always set. |

| 2 | SRST | Host Software Reset bit. When this bit is set the drive |

| | | is held reset. If two drives are daisy chained on the |

| | | interface, this bit resets both drives simultaneously. |

| | | |

| 1 | nIEN | Drive Interrupt Enable bit. The enable bit for the drive |

| | | interrupt to the host. When nIEN is 0 or the drive is |

| | | selected the host interrupt signal INTRQ is enabled |

| | | through a tri state buffer to the host. When nIEN is 1 |

| | | or the drive is not selected the host interrupt signal |

| | | INTRQ is in a hig himpedance state regardless of the |

| | | presence or absence of a pending interrupt. |

| | | |

| 0 | 0 | Always clear. |

+-----+----------+----------------------------------------------------------+

3F7: Read: Drive Address Register

This port returns the drive select and head select addresses for the

drive currently selected. The Drive Address bits are listed in the

table below:

+-----+----------+------------------------------------------------------+

| BIT | Mnemonic | Description |

+-----+----------+------------------------------------------------------+

| 7 | HiZ | This bit is in high impedance when read. |

| 6 | nWTG | Write Gate bit. When a write to the hard drive is in |

| | | progress, nWTG is 0 |

| 5 | nHS3 | Negated MSB of head number |

| 4 | nHS2 | |

| 3 | nHS1 | |

| 2 | nHS0 | Negated LSB of head number. |

| 1 | nDS1 | Drive 1 Select bit. When 0, Drive 1 is selected. |

| 0 | nDS0 | Drive 0 Select bit. When 0, Drive 0 is selected. |

+-----+----------+------------------------------------------------------+

------------------------------------------------------------------------

9. Command Descriptions

The drive decodes and executes commands loaded into the Command Register. In

applications involving two hard drives, both drives receive all commands but

only the selected drive executes commands. The recommended procedure for

executing a command on the selected drive is:

1. Wait for drive to clear BUSY.

2. Load required parameters in the Command Block Registers.

3. Activate the Interrupt Enable (nIEN) bit.

4. Wait for drive to set DRDY.

5. Write the command code to the Command Register.

Execution of the command begins as soon as the drive loads the Command Block

Register. The remainder of this section describes the function of each

command.

90h: Execute Drive Diagnostic

Performs internal diagnostic tests implemented by the drive. Drive 0

sets BUSY within 400 nsec of the receipt of the command.

If Drive 1 is present:

o Both drives execute diagnostics.

o Drive 0 waits up to 5 seconds for Drive 1 to assert PDIAG-

o If Drive 1 does not assert PDIAG-, indicatinf a failure, Drive 0

appends 80h with its own diagnostic status.

o If the host detects a Drive 1 diagnostic failure when reading

Drive 0 status it sets the DRV bit then reads the Drive 1 status.

If Drive 1 is not present:

o Drive 0 reports only its own diagnostic results.

o Drive 0 clears BUSY and generates an interrupt.

If Drive 1 fails diagnostics, Drive 0 appends 80h with its own

diagnostic status and loads that code in the Error Register. If Drive 1

passes its diagnostics or no Drive 1 is present, Drive 0 appends 00h

with its own diagnostic status and loads that in the Error Register.

The Diagnostic Code written to the Error Register is a unique 8 bit

code as listed below.

+------+----------------------------------+

| Code | Description |

+------+----------------------------------+

| 01 | No error detected. |

| 02 | Formatter device error. |

| 03 | Sector buffer error. |

| 04 | ECC circuitry error. |

| 05 | Controller microprocessor error. |

| 8X | Drive 1 failed. |

+------+----------------------------------+

50h: Format Track

The track address is specified in the Sector Count Register. When the

drive accepts this command, it sets the DRQ bit then waits for the host

to fill the sector buffer. When the buffer is full, the drive clears

DRQ, sets BUSY and begins command execution.

ECh: Identify Drive

This command enables the host to receive paramater information from the

drive. When the host issues this command, the drive sets BUSY, stores

the required parameter information in the sector buffer, sets DRQ and

generates an interrupt. The host then reads the information from the

sector buffer. The table below defines the words stored in the buffer.

All reserved fields should be zeros.

+-------+-----------------------------------------------------------------+

| Word | Description |

+-------+-----------------------------------------------------------------+

| 00h | Bit mapped general configuration information. True when bit set |

| | Bit 15: Reserved for non magnetic drives. &nbs

Link to comment
Share on other sites

Forgive my inexperience with this, but am I correct in assuming, based on the above explanations, that this requires either assembly code, or in some other way a binary executable, and direct-reading of particular memory locations?

My experience working with DOS is extremely minimal, and pretty much limited thus far to .BAT files, so I wanted to make sure I understood what was going on before tinkering with anything.

Link to comment
Share on other sites

Forgive my inexperience with this, but am I correct in assuming, based on the above explanations, that this requires either assembly code, or in some other way a binary executable, and direct-reading of particular memory locations?

My experience working with DOS is extremely minimal, and pretty much limited thus far to .BAT files, so I wanted to make sure I understood what was going on before tinkering with anything.

Yes, you'll need to learn a little bit of Asm. It isn't that hard though - here's a little program (11 bytes) that just returns the number of drives according to this method:
The byte at 0040:0075 is also "number of fixed disk drives", according to the IBM PC AT Technical Reference Manual.

mov al, 40
mov ds, ax; segment at 40
mov al, [0075]; get # drives
mov ah, 4c
int 21; return to DOS with errorlevel=# drives

Edited by LLXX
Link to comment
Share on other sites

All,

Well, put my project on hold a bit before, but now I'm getting back into it.

I want to essentially create a Win98Lite boot CD of sorts.

However, what I've been searching for on the web and can't quite get a handle on how to do, is some method that will give me the following:

1) List of hard drives on the system (or the last hard drive) that are NOT cd drives.

2) List of CD drives on the system.

Anyone know how this can be done? I've found a couple of batch file programs that are supposed to be able to show all the drives that exist, but they don't seem to work reliably.

A while ago I found this thread. The objective of the script is different, but in it you'll find references to what you're asking. The script works well and it's well documented, you'll just have to dedicate some time to it to discover how it works. I used parts of it to identify built-in removable drives (mem slots) and remove them because they were interfering with my unattended installation.

http://www.msfn.org/board/index.php?showtopic=18087

Link to comment
Share on other sites

@No6

That script MapDrive.cmd uses DISKPART, i.e. a XP tool, and a number of features that only NT based OS have in their batch interpreter.

@King_V

I presume in your project you somehow boot into DOS, so that you can use DOS batch files only.

If you can explain in more detail when this happens (i.e. in autoexec.bat BEFORE loading mscdex or shsucdx or after it) and exactly what you need this for, maybe I can give you a couple of ideas.

jaclaz

Edited by jaclaz
Link to comment
Share on other sites

I don't know if it could help you but all bootable setup CDs and bootable setup floppy disks for Windows 98 contains utility called FINDCD.EXE and here is a fragment from AUTOEXEC.BAT showing how to start setup from CD-ROM if you don't know the drive letter in advance:

set CDROM=FOO23
FINDCD.EXE
if "%CDROM%"=="FOO23" goto NOCDROM
path=a:\;%CDROM%\
%CDROM%
cd \WIN98
echo.
OEMSETUP.EXE

Apparently it puts the drive letter to the environment variable "CDROM".

Petr

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...