CRU and registers map
Sample programs
Low-level routines
Track-by-track access
Sector access
Checking drive speed
Goofy formats
The card ROM
File buffers in VDP memory
Power-up routine
Device Service Routines
Subprograms
A 74LS259 and a 74LS251 provide as a 8-bit CRU interface. The CRU base address of the card is >1100. The meaning of the 8 bits is the following:
Bit | Meaning when read | Meaning when written to |
---|---|---|
0 | Load head requested (HLD pin) | 1: Select ROM, turn light on |
1 | Drive 1 selected | 1: Strobe motor (for 4.23 sec) |
2 | Drive 2 selected | 0: Ignore IRQ + DRQ |
3 | Drive 3 selected | 1: Signal head loaded (HLT pin) |
4 | 0: Motor strobe on | 1: Select drive 1 |
5 | Always 0 | 1: Select drive 2 |
6 | Always 1 | 1: Select drive 3 |
7 | Selected side | Select side |
As mentionned above, the five registers of the floppy disk controller map in the memory area >FFF0-FFFF. The addresses are different for read operations than for write operations:
Address | I/O | Name |
---|---|---|
>5FF0 | I | Status register |
>5FF2 | I | Track register |
>5FF4 | I | Sector register |
>5FF6 | I | Data register |
>5FF8 | O | Command register |
>5FFA | O | Track register |
>5FFC | O | Sector register |
>5FFE | O | Data register |
Most of the selection logic is provided by an 18-pin custom control chip. Its inputs are mostly address lines (combined via external AND, OR or inverting gates). The outputs control the different parts of the card:
Inputs
Memen*
CRU bit 0 (from 74LS259).
A0 to A7.
Tripple OR gate (74LS27): A4 to A6.
Hex AND gate (74LS30): A4 to A11.
Tripple AND gate (74LS11): AMA&AMB&AMC (always high).
PCBEN (always high).
Ouputs
Enable the first ROM chip.
Enable the second ROM chip.
Enable the FDC (CE* pin), also controls WE* and RE* pins in conjunction
with the A12, A11 and WE* bus lines.
Enable CRU input (74LS251).
Enable CRU output (ORed with CRUCLK* to 74LS259).
Enable data bus transceiver (74LS245) and the RDBEN* bus line.
As mentionned above, the interface is implemented the classical way, with a 74LS251 for CRU input and a 74LS259 for CRU output. With the exception of bit 7, none of the output is directly reflected to an input. So let's examine them separately.
Ouputs (74LS259)
Bit 0: Turn on a LED via a 2N3904 transistor, goes to the
custom
control IC.
Bit 1: Triggers the B input of a 74LS123 one-shot. The A input
is
tied to ground. The cap is 47 uF, the resistor 200K, thus the pulse
lenght
will be 4.23 sec. The one-shot is retriggable though, which means that
the pulse can be prolonged indefinitely by constantly toggling CRU bit
1. The Q output is inverted via a 74LS16 and goes to the disk
connector,
pin 16 (motor on). Before inversion, it also goes to the READY pin of
the
FDC and is combined with CRU bits 4-6 (see below).
Bit 2: Inverted, NORed with the CS* signal for the FDC and the
"ORed"
ouputs of the above one-shot, the IRQ and the DRQ pin combined via two
D flip-flops synchronized by the clock line. When set to 1, it allows
the
IRQ and DRQ pins to inactivate the READY line in the PE-box bus, which
puts the TMS9900 CPU on hold.
Bit 3: Connected directly to the HLT pin of the FDC, provides a
"head loaded" confirmation.
Bit 4: NANDed with bit 1, goes to pin 10 of the drive connector
(SEL1). Also reflected to CRU input bit 1, via a +12V LM2901 buffer and
1K pull-ups to +5V (beats me).
Bit 5: Same as bit 4, to pin 12 of connector (SEL2) and CRU
input
bit 2.
Bit 6: Same as bit 4, to pin 14 of connector (SEL3) and CRU
input
bit 3.
Bit 7: Connected directly to CRU input bit 7, goes to pin 32 of
the drive connector (SIDE) via a 74LS16 inverter.
Inputs (74LS251)
Bit 0: Connected directly to the HLD output pin of the FDC
("please
load head" signal).
Bit 1: Reflects the SEL1 connection, via a LM2901 buffer.
Bit 2: Reflects the SEL2 connection, via a LM2901 buffer.
Bit 3: Reflects the SEL3 connection, via a LM2901 buffer.
Bit 4: Inverted output of the "motor strobe" one-shot.
Bit 5: Grounded.
Bit 6: tied to +5V.
Bit 7: reflects CRU output bit 7.
The card uses a FD1771 single-density-only FDC.
CPU interface
MR* gets its input from a 74LS16 tripple AND gate whose inputs are:
+5V, RESET* bus line and a power-up reset circuit (47 uF cap to ground,
47K to ground, 15K to +5V).
CS* is triggered by the custom control chip.
DAL0-DAL7: connected to D7-D0 via a 74LS245 bus transceiver whose
DIR
pin is controlled by DBIN (via a 74LS244) and enabled by the custom
control
IC (together with RDBEN*).
A0 and A1 are connected to bus lines A14 and A13 respectively.
WE* and RE* are connected to the first two ouputs of a 74LS139 2-to-4
decoder,
whose selection inputs are the A12 and WE* bus lines, and which is
enabled
by the custom control chip (same signal as CS*, ORed with A15).
CLK receives a clock signal from a crystal oscillator. The crystal is a 8MHz NDK080, oscillating via two 74LS04 inverters. The signal is inverted twice via 74LS00 NAND gates (1 pin tied to +5V via 470 ohm resistors), then triggers the CLK input of a 74LS161 4-bit counter. The Q2 output is connected to the Clk pin, thereby providing a 1 MHz clock signal.
INTREQ and DRQ are ORed together and with the inverted motor strobe then go the the D input of a 74LS74 D-flip-flop clocked by the CLKOUT* bus line (buffered by a 74LS244) and cleared by the CS* signal from the custom control chip, via a 74LS04 inverter. The Q output clocks a second 74LS74 whose D input is pulled-up (also cleared by the inverted CS* signal) and whose Q output is ORed with the (non-inverted) CS* signal from the custom IC and CRU bit 2 inverted by a 74LS04. The resulting output is inverted again by a 74LS04 and enabled a 74LS125 buffer whose input is grouded and whose output controls the READY bus line. Got that?
Drive interface
An external data deparator is used, so XTDS is grounded. FDCLK and FDDATA receive their input from pin 30 of the drive connector (READ DATA), via an awfully complicated circuit involving: three 74LS123 one-shots, four 74LS74 D-flip-flop, six 74LS00 NAND gates, four 74LS04 inverters and one 74LS244 buffer.
TR00* receives its input from a 74LS244 buffer, whose input is
pull-up
by a 1K resistor and connected to pin 26 of the drive connector
(TRACK0).
IP* is similarly connected to pin 8 of the connector (INDEX PULSE).
WRPT* is similarly connected to pin 28 of the connector
(W PROTECTED).
READY receives its input from the 74LS123 one-shot that provides the
motor
strobe.
WG is NANDed with the MR* signal and send to pin 24 of the connector
(W GATE).
WD outputs to pin 22 of the drive connector (W DATA) via a 74LS16
inverter.
STEP is similarly connected to pin 18 of the drive connector (STEP) via
a 74LS16 inverter.
DIRC is similarly connected to pin 20 of the drive connector (DIR) via
a 74LS16 inverter.
3PM is connected to +5V to specify a step/dir type of interface.
PH3 and TG43 are not connected.
TEST, WF* and DINT* are not used and are connected to +5V.
Here are some routines that you could use to talk directly to the FDC. Most of them are adapted from the routines in the disk controller card ROM. The main difference when using a double-density CorComp controller is that the card is built around a FD179x that does not invert its data bus. Also, the head-step time must be determined in a fairly complicated way.
* All routines assume that R12 contains the disk controller card's CRU * This routine is used to insert delays between commands. * This routine selects the drive specified in R0 * This routine selects the side specified in R0 * This routine sends a command to the FDC * This routine waits for command completion * This routine should be called after an error occured. * This routine reinitializes the controller card. |
* This routine seeks track 0 and verifies it was reached * This routine moves to the previous track * This routine seeks a given track, whose number is in R1 * This reads a track into a buffer in VDP memory. * This routine formats a track. It assumes the data for the track has been |
You'll have noted that I wrote "format a track" and not "write a track". This is because the FDC interprets most data bytes in the range >F5-FE as formating instructions. Therefore, the "write track" command cannot be used to write a track that contains data, since these data are likely to include such a byte which would screw up the track format.
I don't know how the track copy programs overcome that problem. A possible, although clumsy, solution would be:
* This routine reads the next sector ID block encounted on disk. SIZES DATA 128,256,512,1024 Meaning of the (standard) size code * This routine reads a given sector on the current track into a buffer in VDP memory. * This routine fills a given sector with data from a buffer in VDP memory. |
We saw above that one of the bits in the Status register returns the state of the index hole. We could use it for several purposes.
First, to detect whether there is a disk in the drive. If not, the "hole" will always be here. If there is a disk, the hole will be closed most of the time, and only briefly flash open. If the drive door has been left open, the disk will not rotate and (most probably) the hole will be permanently close.
* This routine tests the drive specified in R0 TSTDSK MOV R11,R9 Save return address LI R1,>1000 Hole is open, see if it stays so for a time CLOSED LI R1,>3000 Hole is closed, see if it stays so CHANGE CLR R0 Hole toggles between open and close |
Another thing we could do is to time the occurences of the hole. This
will
allow us to measure the rotation speed of the drive. Defective drives
could
then be sent out for fine-tuning of their rotation speed (unless you
now
how to adjust it yourself). TI drives spin at 300 rpm nominal, which
means
we should detect the index hole five times per second.
* This routine checks the rotation speed of the drive specified in R0. SPEED MOV R11,R9 Save return address LI R0,4692 Delay for 100 msec (100msec / 64*333ns = 4692) CLR R1 Reset counter MYISR DEC R2 Timer fired: count 100 msec TIMOUT BL @TIMOFF Time out: stop timer and clean up |
NB See the page on the TMS9901 for an explanation of timer interrupts.
Now that we know how to format a track, we can format our disk is all kind of weird ways. All we have to do is to place the proper data in the buffer, then call WRTRAK. The main purpose of doing so would be to prevent standard disk controllers from copying a disk, but there are also less mean reasons.
Sector size
We could format one or more sectors with a size different from the standard 256 bytes. For instance, setting the size length code as >03 in the ID block allows us to use sectors of 1024 bytes. Obviously, only two of these will fit on a track (possibly together with a standard 256-byte sector). This will considerably speed up disk access since we don't need to look for a new sector every 256 bytes. The drawback is that a 1025 bytes long file will use 2048 bytes of disk space: what a waste!
Sector number
Normally, sectors are numbered from 0 to 8 on each track. This is because the sector register is one byte wide, but there are more than 256 sectors on a disk (hopefully).
However, nothing prevents us from scrambling the sector numbers, as long as we know which is where. Thereafter any program trying to access a sector with the "Read sector" or "Write sector" commands will fail, since the sector field in the ID block will never match. But if we know that a sector on track 6 is numbered >A8, we can fetch it easily by placing >A8 in the sector register, while on track 6.
Of course, this is not a very good protection scheme: a simple "Read ID" command will reveal the "secret" sector number to anybody willing to check.
Track / side number
Similarly, we could scramble the track numbering. Note that this will not perturbate the track seeking commands, unless the "V" verify bit was set in the command. However, most disk manager will check that the correct track was reached by reading an ID block. If we number our tracks 1-2-3-144-5-6... all accesses to track 4 are likely to fail.
CRC
Instead of using the >F7 value to tell the FDC to issue the proper CRC, we could place a dummy value in these bytes upon formating. This will cause a CRC error when the user tries to read such an ID (or data) block. Our program will purposedly ignore such errors. However, the missing >F7 code could cause a different problem:
Missing marks
The "Read track" command ends with a "lost data" error if it does not encouter data marks and ID marks (encoded in a special way) where they should be. This is because the command uses these mark to synchronize the flow of bits, and arrange them in bytes. By omiting such a mark, we can make a track unreadable as a whole. However, it will still be accessible for the "Read sector", "Read ID" and "Write sector" commands (except for the sector with the missing mark, of course). NB: there is a way to prevent address mark detection with the FD1771 controller: thus this method is not fool-proofed.
Multiple index holes
You certainly know about "flippies": double-sided disks that can be used in a single-side drive, by just inserting them upside down to access the other side. These disks have a second write-protection notch, symetrical to the original one. They also have a second index hole in the disk envelope, but not in the disk itself. What I'm suggesting here is to do just the opposite: pierce a second hole in the disk itself, but not in the envelope. This will effectively abort the "Read track" command when the second hole is encountered and prevent track-by-track copying.
On the other hand, the "Read ID", "Read sector" and "Write sector" will operate normally since they only abort after 5-6 occurences of an index hole.
Once again, this is not a very good protection method since the bad guy can just tape the extra hole shut!
Pin hole in the media
This method was sometimes used in the PC world: make a small hole in the disk (using a laser) then detect the position of the hole to ensure the disk is an original.
We could do this with a pin: make a scratch or a small hole towards the outside of the disk (but not completely to the rim, to avoid damaging sector 0 and 1). Then use a disk manager to locate the position of the damage on the disk and include this information in your program
The protected program will then look for the presence of the damage in one or more sectors and react accordingly. Please don't make it a JEQ/JNE test: a quick disassembly will allow any hacker to bypass your protection. A more clever scheme would be to encrypt your main program and to place the (preferably long) key in a damaged sector, at a fixed distance from the damage.
To locate a damaged sector, your program can just read it, invert every byte, and write it back. Then read it again: the damaged bytes won't be inverted (just don't forget to restore the other bytes once you're done).
The controller card comprises a 8192 bytes (>2000) ROM that contains a power-up subroutine, four DSR for high-level file access and many subprograms for low- or mid- or high-level disk access. As usual with peripheral cards, that ROM appears at >4000-5FFF when CRU bit 0 is set to one for that card. Note that the controller's register map at >5FF0-5FFF, thus the last 16 bytes of the ROM cannot be accessed. You'll find a commented disassemly listing of the whole ROM on my download page (warning: it's written in an ugly programming style).
Upon initialisation, the disk controller power-up routine reserves room for three files at the end of the VDP memory. Subsequently, the subroutines FILES (to be called from Basic) or >16 (to be called from assembly) can modify the amount of memory reserved, from 1 to 16 files. The bottom of the reserved area (i.e. the highest free address) is pointed at by >8370.
This memory area is used by the disk controller to store characteristics of the current disk, and of the currently accessed files. It has the following structure (exemple with 3 files):
Address | Bytes | Name | Contents |
---|---|---|---|
>37D8 | 5 | Buffer area header | Validation code: >AA |
>37D9 | Pointer to top of buffer: >3FFF | ||
>37DB | CRU base of disk controller card: >11 | ||
>37DC | Max number of files (here: >03) | ||
>37DD | 6 | File control block for first file |
Current sector offset in file ( 2 bytes) |
>37DF | Sector number of FDR (2 bytes) | ||
>37E1 | Record offset in sector (for Var only) | ||
>37E2 | Drive number (add >80: modified data) | ||
>37E3 | 256 | FDR for first file |
Copied from disk (add >80 to first byte to signal a modified FDR). |
>38E3 | 256 | Data buffer for first file |
Contents of current sector data block |
>39E3 | 6 | File control block for second file |
See above |
>39E9 | 256 | FDR for second file |
See above |
>3AE9 | 256 | Data buffer for second file |
See above |
>3BE9 | 6 | File control block for third file |
See above |
>3BEF | 256 | FDR for third file |
See above |
>3CEF | 256 | Data buffer for third file |
See above |
>3DEF | 252 | VDP stack | Used by the routines in the controller card |
>3EEB | 4 | Disk drive info | Last drive number accessed (>01 - 03) |
>3EEC | Last track accessed on drive 1 | ||
>3EED | Last track accessed on drive 2 | ||
>3EEE | Last track accessed on drive 3 | ||
>3EEF | 6 | Not used | Meant for TI-99/4 (not 4A) ? |
>3EF5 | 256 | VIB copied from sector 0 |
Copied from last drive accessed for a write |
>3FF5 | 11 | Filename compare | Disk number |
>3FF6 | Filename |
This routine performs the equivalent of a CALL FILES(3), i.e. it reserves room for three file acess blocks at the end of the VDP memory.
There are four DSR subroutines in the original TI disk controller card:
DSK1 accesses the first disk drive
DSK2 accesses the second disk drive
DSK3 accesses the third disk drive
DSK expects a disk name after a decimal point (e.g.
DSK.DISKNAME)
and accesses the drive that contains this disk (if any).
A file name should be provided after the DSR name, using a decimal point as a separator (e.g. DSK1.MYFILE). If no filename is provided after the dot, the disk directory is accessed as a read-only, D/F 38 file.
If the disk directory is accessed, only opcode 0-2 (Open, Close and Read) are recognized. Otherwise, the DSRs understands all the standard PAB opcodes, except for Scratch Record (>08).
Opens a file, either exisiting or new. Puts its characteristics in a file access block in VDP memory, provided there is one free.
Closes the file. Frees the file access block in VDP memory.
Input data from a file, one record at a time. Data is transfered into a buffer located in VDP memory.
Writes data to a file, one record at a time . Data is taken from a buffer in VDP memory.
Sets the internal pointer to a given record in a relative file, to record 0 in a sequential file.
Loads a memory image ("program") file into a buffer in VDP memory.
Saves data in a "program" file, from a buffer located in VDP memory.
Removes a file from the disk directory.
Not implemented. Returns with "bad attributes" (why not "illegal opcode"?).
Returns the status of the specified file according to the following format:
>80: File not found
>40: File is write protected
>20 (not used)
>10: File is internal
>08: File is program
>04: File is variable
>02: Memory full
>01: EOF reached
Allows to catalog a disk by opening a file called "DSKx." or "DSK.DISKNAME." (i.e. missing a filename).
Record 0 provides disk informations, records 1 through 128 provide file informations.
Most of these subprograms have 1-char long names, the character being in the range >10 to >16. Therefore, they cannot be called from Basic (the only exception is FILES). Each subprogram expects parameters to be passed at specific addresses in the scratch-pad RAM (generally >834A->8350).
Subprograms can be classified in three categories.
This subprogram reads or writes a sector from the disk. The number of bytes is always 256.
Input parameters
>834A | - | |
>834C | Drive # (1-3) | 0: write <>0: read |
>834E | VDP buffer address | |
>8350 | Sector number |
Output parameters
>834A | Sector number | |
>834C | - | - |
>834E | - | |
>8350 | Error code |
This routine formats a disk.
Input parameters
>834A | - | |
>834C | DSR / Drive # | # of tracks |
>834E | VDP buffer address | |
>8350 | Density | # of sides |
DSR: 0 = standard format, can be done by DSR version 1.0
1 = needs DSR version 2.0 (double-sided, or track # not 35 nor 40)
2 = needs a higher DSR version (double density, etc)
Output parameters
>834A | # of sectors / disk | |
>834C | - | - |
>834E | - | |
>8350 | Error code |
This routine is used to modify the protection status of a file, i.e whether the file can or cannot be deleted and modified.
Input parameters
>834C | Drive # (1-3) | 0: unprotected >FF: protected |
>834E | Filename ptr (in VDP mem) | |
>8350 | - |
The filename must be a left-justified, 10-char string. Add as many trailing spaces as necessary.
Output parameters
>834C | - | - |
>834E | - | |
>8350 | Error codes |
This routine changes the name of a file on a given drive.
Input parameters
>834C | Drive # (1-3) | - |
>834E | New name ptr (in VDP mem) | |
>8350 | Old name ptr (in VDP mem) |
Filenames must be 10 character strings, with as many trailing spaces as necessary. No check is made to ensure that the new name is legal!
Output parameters
>834C | - | - |
>834E | - | |
>8350 | Error codes |
This routine reads data from a file sector-wise, irrespective of its type, record length, etc. For instance, it can read a "program" file by chunks of 512 bytes (or whatever is convenient).
Input parameters
>834C | Drive # (1-3) | # of sectors |
>834E | Filename ptr (in VDP mem) | |
>8350 | Info ptr (>83xy) | - |
# of sectors: 0 = Get file info (fill the structure below, using
data
from the file's FDR)
<>0 = Read that number of sectors (from first sector indicated in
the structure below).
>83xy | VDP buffer address | |
+2 | First sector # | |
+4 | File type | Recs / sector |
+6 | EOF offset | Rec lenght |
+8 | # of rec | - |
Output parameters
>834C | - | # of sectors read |
>834E | - | |
>8350 | Error codes |
Result of get file info:
>83xy | - | |
+2 | - | |
+4 | File type | Recs / sector |
+6 | EOF offset | Rec lenght |
+8 | # of rec | - |
This routine writes data to a file sector-wise, irrespective of its type, record lenght etc.
Input parameters
>834C | Drive # (1-3) | # of sectors |
>834E | Filename ptr (in VDP mem) | |
>8350 | Info ptr (>83xy) | - |
# of sectors: 0 = Create file (using info in the structure below to
create the FDR)
<>0 = Write that number of sectors (from first sector indicated
in
the structure below).
>83xy | VDP buffer address | |
+2 | First sector # | |
+4 | File type | Recs / sector |
+6 | EOF offset | Rec lenght |
+8 | # of rec | - |
Output parameters
>834C | - | # of sectors writen |
>834E | - | |
>8350 | Error codes |
This subprogram sets the number of file access blocks reserved at the end of the VDP memory. Thus, it controls the number of files that can simultaneously be open. The maximum is 16.
Input parameters
>834C | # of files(1-16) | - |
>834E | - | |
>8350 | - |
Output parameters
>834C | - | - |
>834E | - | |
>8350 | Error codes |
This is the same subprogram as >16, except that it is meant to be called from Basic. It limitates the number of files to 9.
Models
Connection cable
Terminal resistor pack
Shunt pack
Power supply
Many 5/25" floppy drives are compatible with the TI-99/4A disk controller. Here are a few examples:
Texas Instruments PHP1250
Magnetic Peripherals BR8B1A
Mitsubishi M4851-362U
MPI 51 & 52
Pertec FD200
Qumetrak 142
Remex RFD480
Shugart 400L, 450
Siemens 82, FDD100-5
Tandon TM65-2, Tm100-2A
Wango 82
The connection cable follows a standard convention:
# I/O Name Function
-- ---- --------------- ---------
2 ? (used on PCs, for 1.44 MB drives)
4 - not used
6 > SEL4 Select DSK4 (not on original TI FDC)
8 < INDEX Index pulse (hole in floppy detected)
10 > SEL1 Select DSK1
12 > SEL2 Select DSK2
14 > SEL3 Select DSK3
16 > STROBE Motor on
18 > DIR Direction to step at (0=out, 1=in)
20 > STEP Step by one track
22 > WDATA Data output
24 > WGATE Enable data output
26 < TRACK0 Track 0 reached
28 < WPROTECT Write protection detected
30 < RDATA Data input
32 > SIDE Side selection
34 - not used
All odd numbered pins are connected to ground
So that you don't have to set your drive number yourself, Texas Instruments provided small connectors that redirect the SEL1, SEL2 and SEL3 lines, in the following way:
Controller Drive 1 Connector Drive 2 Connector Drive 3
SEL1 >------ SEL1 ------ ,---------- SEL1 ------ ,---------- SEL1
SEL2 >------ SEL2 -------' ,-------- SEL2 -------' ,-------- SEL2
SEL3 >------ SEL3 ---------' ------- SEL3 ---------' ------- SEL3
See how it works? All drives are set to react to SEL1, but for the second drive SEL1 is actually connected to the SEL2 line. Similarly, for the last drive, SEL1 is actually connected to the SEL3 line. This technique is known as "wire twisting".
Some of the connection lines require a pull-up resistors: SEL1, SEL2, SEL3, STROBE, DIR, SETP, WDATA and WGATE. For reasons that are not very clear to me, the pull-up resistors must be located at the far end of the cable, i.e. in the last drive in the chain. This means that this drive MUST ALWAYS BE TURNED ON, even if you are not actually using it. Otherwise signals will not carry properly.
Normally, all drives come out of factory with a resistor pack installed. However, we cannot leave the pack in place in each drive as this would pull up the lines too strongly and may damage the controller card. Therefore, you MUST remove the resistor pack from each drive but the last one in the chain. Let me mellow that: in fact, this depends on the value of the resistor. Most drives use 150 ohm resistor, and having more than 1 pack installed may damage the card, but some manufacturers (e.g. TEAC) use 500 ohm resistors and these can be left in place without any risk of damaging the controller (three 500 ohms resistors in parallel add up to 167 ohms).
Most of the time, the resistors come in the form of a DIP pack (dual-in-line) that looks like a small integrated circuit. It is generally installed on a socket, so you can remove it easily. Make sure you save it, in case you want to reinstall it later...
As floppy disk drives were built to work on many different systems, they can be configure according to the user's needs. Sometimes, this is done by cutting connections on a so-called shunt pack. Occasionally, the shunt pack is replaced with a DIP-switch pack which only requires flipping tiny switches. Finally, you may encounter jumpers, i.e. two small pins connected by a little cap: just remove the cap to open the connection.
The problem is that, even though there is a convention on which options should be made available, each manufacturer does things in a slightly different way, labels the connections with different names, arranges them in a different order, or even splits the pack in several jumpers. Normally, you should see a single 14 or 16-pin pack (or switch) with the following labels:
HL or HS or H: Head loaded by drive selection line.
DS0 or DS1: Drive selected by SEL1.
DS1 or DS2: Drive selected by SEL2.
DS2 or DS3: Drive selected by SEL3.
DS3 or DS4: Drive selected by SEL4.
MX or X: mutiplex. Caution: DS4 and MX are often inverted.
HM or MH or M: Head loaded by the Strobe signal.
In case of doubt, follow the SEL1 connection (pin 10 on the cable) and see where it ends in the shunt pack.
As mentionned above, all drives should respond to SEL1, because we are using twisted connectors to redirect SEL2 and SEL3 to the SEL1 line. Thus, open all DS connections, except for DS0 (sometimes labelled DS1). If you decide for a straight cable solution (for instance, if you have twin, slim drives) connect the line you want and leave the other three open. Each drive should have one and only one DSx line connected.
HL and HM are mutually exclusive. They determine which signal should cause the magnetic head to be loaded on the disk: the SELx signal or the STROBE signal. Normally, you would want it to be the selection signal, so that only the drive you are accessing loads its head. To this end, connect HL and open HM. However, if you have only one drive, using HM may result in a slightly better performance (in this case, you should also connect MX).
MX determines whether the drive output lines should be enabled by the selection signal (MX open) or be permanently enabled (MX connected). Obviously, when using multiple drives MX should be left open. In a single-drive system, connecting MX may slightly improve the drive performance.
The power connector in the drive looks like this (looking inside the drive plug):
,---+Preliminary version. 3/19/99. Not for release.
| O | +12V
| O | Gnd (for 12V)
| O | Gnd (for 52V)
| O | +5V
`---+