Iomega Zip and Jaz drive notes
This is a collection of arcana on Zip drives you (might not) find anywhere else…
Things I'm looking for
If you have any of these documents, please drop me a line at philpem@gmail.com.
- Iomega PPA3 Parallel Port SCSI HBA documentation
- This is apparently quite an old thing which seems to date back to the days of the Bernoulli Box. I expect documentation is quite hard to find!
- Iomega document EN144302 – title unknown
- According to comments in the Linux IMM driver, this is the spec for the MatchMaker (IMM) chip which replaced the PPA.
- From the same source, Iomega would (as of 1998) send this to driver developers.
- Any Iomega documentation covering Zip or Jaz drive programming, SCSI commands, interfacing, schematics, service manuals… anything more technical than a user's manual.
Hardware
The Zip and Jaz drives are, by and large, SCSI removable mass storage devices. Somewhat surprisingly this even applies to the parallel-port drives, which have either an PPA3 (Parallel Port Accessory, aka VP0) or MatchMaker (Iomega IMG VP1) chip to convert from SCSI to parallel.
The drive's main processor is an Iomega ASIC – in parallel drives this tends to be a PHAEDRUS
chip which talks to an AIC-7110 SCSI controller, while in ATAPI drives it's a RUCIFY
chip which talks directly to the IDE bus. An Iomega patent, US5809520A, gives more information on Phaedrus: it contains an 8032 microcontroller core, 1K of RAM and the data encoding/decoding logic.
From there, there's a read-channel IC (ATAPI: TI 34P3410; parallel: IMP 62C538) and a spindle motor driver (ATAPI: TI TLS2247; parallel: Philips TDA5341G) which interface the processor to the drive mechanics. The ASIC has an external firmware ROM – either a 27C512 (parallel drives) or an AT27LV520 (ATAPI drives).
Chip function | Zip 100 SCSI External | Zip 100 Parallel | Zip 100 ATA | Zip 100 ATAPI | Zip 250 IDE/ATAPI | Zip 250MB PC/MAC with PCMCIA option | |
---|---|---|---|---|---|---|---|
Board codename | ZI5341S (1995) | Z5341PI (1996) | Zip PPI (1997) | | | ATAPI 250 | Sybil |
Main ASIC | Phaedrus 02430600 | Phaethon 02590303 | Bruno | Rucify 03045005 | Bruno 03282001 | |
|
Read channel | IMP 62C538-136BJ | | TI 34P3410 | ||||
Spindle motor driver | Philips TDA5341G | TI TLS2247 | |||||
Firmware ROM | M27C512 (ST) | Atmel AT27LV520 | |||||
Interface/ASIC? | Adaptec AIC-7110Q | Adaptec AIC-7110Q NEC 02415400 IMGVP0 | NEC | TI 03874600 / F721905PAG | |||
Head amp | TI PTS21H52-3 |
The internal codename is usually printed on a label attached to the PCB.
Board photos used to derive the table above:
- Zip 100 Parallel, early version: https://commons.wikimedia.org/wiki/File:Mainboard_of_Iomega_ZIP-100,_parallel_port_printer_pass-through-7813.jpg
- Zip 100 Parallel (Zip PPI with Phaethon, Z100P2) teardowns:
- Zip 100 ATA information and board shots: https://www.experimental-engineering.co.uk/2011/02/16/ide-zip-drive/
- Zip 250MB “PC/Mac” with USB and PCMCIA options: https://www.ifixit.com/Teardown/Iomega+ZIP+250+MB+External+USB+Teardown/132306
Zip Drive proprietary SCSI commands and mode pages
Acknowledgements
This section is based on what I've found by poking and prodding a Zip Plus (hybrid parallel/SCSI) drive with FWB Hard Disk Toolkit, and from the source code of Trouble in Paradise (by Steve Gibson) and parts of the SCSIQuery Amiga utility sources which were sent to me by Thomas Richter.
Thanks also to Martin, for the PowerMac 7300 G3 which DPD turned into a repair project! I'm not sure I could have figured out the gory details of the 2F
mode page without it.
Mode Page 2F: Iomega-specific mode settings
These parameters are written with a Mode Select (CMD 15h) CDB like this:
``` 1525 200.088_290_628 CMD - Mode Sel(6) 15 10 00 00 12 00 1526 200.088_746_876 DataOut (N) 00 00 00 08 00 00 00 00 ........ 00 00 02 00 2F 04 5C 0F ..../.\. FF 0F .. (18 Bytes) CDB: Cmd = 15h Flags = 10h -- PF=1 (SCSI-3 format) Param List Length = 12h = 18 bytes Mode parameter header(6) Mode data length = 0 (byte 0) Medium type = 0 (byte 1) Device-specific = 0 (byte 2) Block Descriptor Len = 8 (byte 3) Block descriptor: Number of blocks = 0 (bytes 0-3, big endian) Reserved = 0 (byte 4) Logical block length = 512 (bytes 5-7, big endian) Mode page: Page code = 2Fh (Iomega Zip vendor-specific parameters mode page) (byte 0) Page length = 4 (byte 1) Page data as below -- 4 bytes
Strictly speaking, the mode data length field should be set to 11h (17 decimal) but the FWB software sends a length of zero. I have no idea if the Zip drive requires this, or if it's a bug in FWB's software. Either way, the Zip drive doesn't seem to care.
The current settings may be queried with a Mode Sense (CMD 1Ah) CDB like this:
1575 203.617_717_096 CMD - Mode Sns(6) 1A 00 2F 00 12 00 1576 203.618_844_428 DataIn (N) 11 00 00 08 00 00 00 00 ........ 00 00 02 00 2F 04 5C 0F ..../.\. FF 0F .. (18 Bytes) CDB: Cmd = 1Ah Flags = 00h Page code = 2Fh (Iomega Zip vendor-specific parameters); Page Control = 00b (current values) Subpage code = 00h Param List Length = 12h = 18 bytes
Mode page format
The mode page format is 4 bytes, organised as follows:
ff | ss | tt | uu |
ff
: Flags, see below. (default 0x5C = SCRUB+FTME+RIDI+OFFTR)ss
: Spindown timer in minutes, 1 to 255. 0 disables. (default 15)tt
: Park timer, 0-255. 0 disables. (default 255)uu
: Max read retries, 0-15. (default 15)
The flag bits are as follows:
Bit | Mnemonic | Function |
---|---|---|
b0 (LSB) | - | Always 0 |
b1 | PHSK | Physical Seek |
b2 | OFFTR | Off Track |
b3 | RIDI | Read IDs Intelligently |
b4 | FTME | Fault Tolerant Mode Enable |
b5 | VSC | Vendor Specific Commands |
b6 | SCRUB | Head Cleaning on error |
b7 (MSB) | DHS | Disable Head Sweep |
CMD 06: Vendor Unique, SCSI status pages
The majority of this is from the ReadIOX function in the SCSIQuery source code.
These are accessed with CMD 06 “vendor unique”:
06 | ff | pp | 00 | nn | 00 |
06
: command code (always 6)ff
: Flags (always 0)pp
: Page number- 1: Format Status (IOPA_DEFECT_DATA)
- 2: Disk Status (IOPA_DEVICE_DATA)
00
: reserved (always 0)nn
: Length00
: control (always 0)
Format Status page (IOPA_DEFECT_DATA)
Information about this is from the IOXDefectData structure in the SCSIQuery source code.
TODO: Example data
* 00..01h: WORD: Count1 * 02..03h: WORD: Count2 * 04h:
Disk Status page (IOPA_DEVICE_DATA)
Information about this is from the Trouble In Paradise and SCSIQuery source code (IOXData, JOXData structures).
Old form
Same as New Form but without the two prefix bytes.
Can be identified by checking if the first two bytes are equal to the page number and the length requested less two, e.g. `02 3D`.
New form
368 46.492_507_276 CMD - Vendor Uniq. 06 00 02 00 3F 00 369 46.493_330_964 DataIn (N) 0h: 02 3D 00 02 00 00 02 FF .=...... 8h: FF 00 00 02 00 00 75 00 ......u. 10h: 09 00 7E 00 00 00 31 30 ..~...10 18h: 38 31 39 30 34 31 35 30 81904150 20h: 32 39 36 31 39 38 30 32 29619802 28h: 5A 49 50 20 20 20 20 4B ZIP K 30h: 41 4D 30 37 20 20 20 20 AM07 38h: 20 20 20 20 20 20 01 . (63 Bytes) ``` * 00h: BYTE. Page number * 01h: BYTE. Data length * 02..03: WORD. :?: * 04: BYTE. :?: * 05..08h: DWORD. Maximum LBA. (= 0x0002FFFF) * 09..0Ch: DWORD. Block size. (= 512) * 0D..0Eh: WORD. Side 0 remaining spares count * 0F..10h: WORD. Side 0 bad sectors count * 11..12h: WORD. Side 1 remaining spares count * 13..14h: WORD. Side 1 bad sectors count * 15h: BYTE. Protection status
The following are seemingly only present in the New Style Mode Page, on Zip Plus and Jaz drives
* 16..27h: CHAR[18]. Cartridge serial number? (DiskID) * 28..2Eh: CHAR[7]. Cartridge type? (DiskType) * 2F..3Dh: CHAR[15]. Date code? (VendorCode) * 3Eh: BYTE. Count1
Jaz drives also include the following:
* 3Fh: BYTE. Count2 * 40..41h: WORD: Jaz reserved. * 42..43h: WORD: Jaz format life * 44..45h: WORD: Jaz disk life
Calculating disk life (Zip disks)
This requires both the IOPA_DEVICE_DATA
and IOPA_DEFECT_DATA
pages to be read in.
First do some pre-calculations:
DeviceDataStruct ioxdata; DefectDataStruct ioxdd; Spare1 = ioxdata->Free0; Spare2 = ioxdata->Free1; Bad1 = ioxData->Bad0; Bad2 = ioxdata->Bad1; ioTotal1 = ioxdd->TotalCount; ioGood1 = ioxdd->OKCount; if (ioxdd->BadFlag) { // extra data present for other side ioTotal2 = ioxdd->Total2Count; ioGood2 = ioxdd->OK2Count; } else { // data is collapsed into one field ioTotal2 = ioxdd->TotalCount; ioGood2 = ioxdd->OKCount; } if (ioTotal1 < ioTotal2) { ioTotal2 = ioTotal1; } if (ioGood1 < ioGood2) { ioGood2 = ioGood1; }
Calculate the disk life:
int diskLife, div; diskLife = ioGood2 + ioTotal2 - Bad1 - Bad2; div = ioGood1 + ioTotal1; if (div) { disklife = (disklife * 100) / div; } else { disklife = 0; } Calculate the format life: <code c> if (Spare1 > Spare2) { format = ioSpare2 * 100; div = ioSpare2 + Bad2; } else { format = ioSpare1 * 100; }
Calculating disk life (Jaz disks)
Disk Life (as a percentage) can be calculated with:
DiskLife = (joxData->DiskLife * 100) / 2556;
Format life (as a percentage) is a little trickier:
int format = 0xFF - joxData->FormatLife; if (format < 0) { format = 0; } else { format = (format * 100) / 255; }
Now isn't that easier than Zip disks?
CMD 0C: Disk read/write and password protection
TBD.