Update from Hauke to resolve some relatively severe performance problems.

This commit is contained in:
scottr 1999-03-27 05:45:19 +00:00
parent b15dc3ed17
commit 5e3349678a
5 changed files with 1214 additions and 617 deletions

View File

@ -1,7 +1,7 @@
/* $Id: iwm.s,v 1.1 1999/02/18 07:38:26 scottr Exp $ */
/* $NetBSD: iwm.s,v 1.2 1999/03/27 05:45:19 scottr Exp $ */
/*
* Copyright (c) 1996-98 Hauke Fath. All rights reserved.
* Copyright (c) 1996-99 Hauke Fath. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -46,6 +46,11 @@
* would be lost.
* The old status register content is stored on the stack.
*
* o We run at spl4 to give the NMI switch a chance. All currently
* supported machines have no interrupt sources > 4 (SSC) -- the
* Q700 interrupt levels can be shifted around in A/UX mode,
* but we're not there, yet.
*
* o As a special case iwmReadSectHdr() must run with interrupts disabled
* (it transfers data). Depending on the needs of the caller, it
* may be necessary to block interrupts after completion of the routine
@ -60,7 +65,7 @@
#include <m68k/asm.h>
#include "iwm_regs.s"
#include <mac68k/obio/iwmreg.h>
#define USE_DELAY 0 /* "1" bombs for unknown reasons */
@ -69,8 +74,8 @@
* References to global name space
*/
.extern _TimeDBRA | in mac68k/macrom.c
.extern _IWMBase | in mac68k/machdep.c
.extern _VIA1Base |
.extern _VIA1Base | in mac68k/machdep.c
.extern _IWMBase | in iwm_fd.c
.data
@ -205,13 +210,8 @@ quDone:
ENTRY(iwmReadSectHdr)
link a6,#0
moveml d1-d5/a0-a4,sp@-
movel _IWMBase,a0
movel _Via1Base,a1
movel a6@(0x08),a4 | Get param block address
bsr readSectHdr
moveml sp@+,d1-d5/a0-a4
unlk a6
rts
@ -251,7 +251,7 @@ ENTRY(iwmInit)
tstb a0@(q6H)
andb a0@(q7L),d0 | status register
tstb a0@(q6L)
cmpib #0x17,d0 | all is well??
cmpib #iwmMode,d0 | all is well??
beq initDone
/*
@ -270,9 +270,9 @@ initLp:
bclr #5,d0 | Reset bit 5 and set Z flag
| according to previous state
bne initLp | Loop if drive still on
cmpib #0x17,d0
cmpib #iwmMode,d0
beq initDone
moveb #0x17,a0@(q7H) | Init IWM
moveb #iwmMode,a0@(q7H) | Init IWM
tstb a0@(q7L)
bra initLp
@ -644,49 +644,55 @@ stDone:
* Add a branch for Verify (compare to buffer)
* Understand and document the checksum algorithm!
*
* XXX make "sizeof cylCache_t" a symbolic constant
*
* Parameters: fp+08 l Address of sector data buffer (512 bytes)
* fp+12 l Address of sector header struct (I/O)
* fp+16 l Address of cache buffer ptr array
* Returns: d0 result code
* Local: fp-2 w CPU status register
* fp-3 b side,
* fp-4 b track,
* fp-5 b sector wanted
* fp-6 b retry count
* fp-7 b sector read
*/
ENTRY(iwmReadSector)
link a6,#-6
link a6,#-8
moveml d1-d7/a0-a5,sp@-
movel _IWMBase,a0
movel _Via1Base,a1
movel _Via1Base,a1
movel a6@(o_hdr),a4 | Addr of sector header struct
movel a6@(12),a4 | Addr of sector header struct
moveb a4@(0),a6@(-3) | Save side bit,
moveb a4@(1),a6@(-4) | track#,
/* moveb a4@(2),a6@(-5) | sector# */
moveb a4@+,a6@(-3) | Save side bit,
moveb a4@+,a6@(-4) | track#,
moveb a4@,a6@(-5) | sector#
moveb #2*maxGCRSectors,a6@(-6) | Max. retry count
movew sr,a6@(-2) | Save CPU status register
oriw #0x0700,sr | Block all interrupts
oriw #0x0600,sr | Block all interrupts
rsNextSect:
movel a6@(o_hdr),a4 | Addr of sector header struct
bsr readSectHdr | Get next available SECTOR header
bne rsDone | Return if error
/*
* Is this the right track & side? If not, return with error
*/
movel a6@(12),a4 | Sector header struct
movel a6@(o_hdr),a4 | Sector header struct
moveb a4@(0),d1 | Get actual side
moveb a4@(o_side),d1 | Get actual side
lsrb #3,d1 | "Normalize" side bit (to bit 0)
andb #1,d1
moveb a6@(-3),d2 | Get wanted side
eorb d1,d2 | Compare side bits
bne rsSeekErr | Should be equal!
moveb a6@(-4),d1 | Get wanted track#
cmpb a4@(1),d1 | Compare to the read header
moveb a6@(-4),d1 | Get track# we want
cmpb a4@(o_track),d1 | Compare to the header we've read
beq rsGetSect
rsSeekErr:
moveq #seekErr,d0 | Wrong track or side found
bra rsDone
@ -694,13 +700,14 @@ rsSeekErr:
/*
* Check for sector data lead-in 'D5 AA AD'
* Registers:
* a0 points to data register of IWM
* a2 points to 'diskTo' translation table
* a0 points to data register of IWM as set up by readSectHdr
* a2 points to 'diskTo' translation table
* a4 points to tags buffer
*/
rsGetSect:
moveb a4@(2),a6@(-7) | save sector number
lea a4@(3),a4 | Beginning of tag buffer
moveq #50,d3 | Max. retries to seek
moveq #50,d3 | Max. retries for sector lookup
rsLeadIn:
lea dataLeadIn,a3 | Sector data lead-in
moveq #0x03,d4 | is 3 bytes long
@ -716,6 +723,7 @@ rsLI2:
bne rsLeadIn | If ne restart scan
subqw #1,d4
bne rsLI1
/*
* We have found the lead-in. Now get the 12 tag bytes.
* (We leave a3 pointing to 'dataLeadOut' for later.)
@ -775,15 +783,27 @@ rsTagNyb4:
subqw #3,d4 | Update byte counter (four 6&2 encoded
bpl rsTags | disk bytes make three data bytes).
/*
* Jetzt sind wir hier...
* ...und Thomas D. hat noch was zu sagen...
*
* We begin to read in the actual sector data.
* Compare sector # to what we wanted: If it matches, read directly
* to buffer, else read to track cache.
*/
movel a6@(8),a4 | Sector data buffer
movew #0x01FE,d4 | Loop counter
moveq #0,d1 | Clear d1.L
moveb a6@(-7),d1 | Get sector# we have read
cmpb a6@(-5),d1 | Compare to the sector# we want
bne rsToCache
movel a6@(o_buf),a4 | Sector data buffer
bra rsData
rsToCache:
movel a6@(o_rslots),a4 | Base address of slot array
lslw #3,d1 | sizeof cylCacheSlot_t is 8 bytes
movel #-1,a4@(o_valid,d1)
movel a4@(o_secbuf,d1),a4 | and get its buffer ptr
rsData:
rsDatNyb1:
moveb a0@,d3 | Get 2 bit nibbles
@ -884,7 +904,6 @@ rsBadDBtSlp:
moveq #badDBtSlp,d0 | One of the data mark bit slip
bra rsDone | nibbles was incorrect
/*
* We have gotten the checksums allright, now look for the
* sector data lead-out 'DE AA'
@ -900,13 +919,36 @@ rsLdOut1:
bne rsBadDBtSlp | Fault!
dbra d4,rsLdOut1
moveq #0,d0 | OK.
/*
* See if we got the sector we wanted. If not, and no error
* occurred, mark buffer valid. Else ignore the sector.
* Then, read on.
*/
rsDone:
movel a6@(o_hdr),a4 | Addr of sector header struct
moveb a4@(o_sector),d1 | Get # of sector we have just read
cmpb a6@(-5),d1 | Compare to the sector we want
beq rsAllDone
tstb d0 | Any error? Simply ignore data
beq rsBufValid
lslw #3,d1 | sizeof cylCacheSlot_t is 8 bytes
movel a6@(o_rslots),a4
clrl a4@(o_valid,d1) | Mark buffer content "invalid"
rsBufValid:
subqb #1,a6@(-6) | max. retries
bne rsNextSect
| Sector not found, but
tstb d0 | don't set error code if we
bne rsAllDone | already have one.
moveq #sectNFErr,d0
rsAllDone:
movew a6@(-2),sr | Restore interrupt mask
moveml sp@+,d1-d7/a0-a5
unlk a6
rts
rts
/*
@ -915,40 +957,45 @@ rsDone:
* TODO: Poll SCC as long as interrupts are disabled (see top comment)
* Understand and document the checksum algorithm!
*
* Parameters: fp+8 l Address of sector data buffer (512 bytes)
* fp+12 l Address of sector header struct (I/O)
* XXX Use registers more efficiently
*
* Parameters: fp+8 l Address of sector header struct (I/O)
* fp+12 l Address of cache buffer ptr array
* Returns: d0 result code
*
* Local: fp-2 w CPU status register
* fp-3 b side,
* fp-4 b track,
* fp-5 b sector wanted
* fp-6 b retry count
* fp-10 b current slot
*/
ENTRY(iwmWriteSector)
link a6,#-6
link a6,#-10
moveml d1-d7/a0-a5,sp@-
movel _IWMBase,a0
movel _Via1Base,a1
movel _Via1Base,a1
movel a6@(o_hdr),a4 | Addr of sector header struct
movel a6@(12),a4 | Addr of sector header struct
moveb a4@(0),a6@(-3) | Save side bit,
moveb a4@(1),a6@(-4) | track#,
moveb a4@(2),a6@(-5) | sector#
moveb a4@+,a6@(-3) | Save side bit,
moveb a4@+,a6@(-4) | track#,
moveb a4@,a6@(-5) | sector#
moveb #maxGCRSectors,a6@(-6) | Max. retry count
movew sr,a6@(-2) | Save CPU status register
oriw #0x0700,sr | Block all interrupts
oriw #0x0600,sr | Block all interrupts
wsNextSect:
movel a6@(o_hdr),a4
bsr readSectHdr | Get next available sector header
bne wsDone | Return if error
bne wsAllDone | Return if error
/*
* Is this the right track & side? If not, return with error
*/
movel a6@(12),a4 | Sector header struct
movel a6@(o_hdr),a4 | Sector header struct
moveb a4@(0),d1 | Get side#
moveb a4@(o_side),d1 | Get side#
lsrb #3,d1 | "Normalize" side bit...
andb #1,d1
moveb a6@(-3),d2 | Get wanted side
@ -956,26 +1003,39 @@ ENTRY(iwmWriteSector)
bne wsSeekErr
moveb a6@(-4),d1 | Get wanted track#
cmpb a4@(1),d1 | Compare to the read header
cmpb a4@(o_track),d1 | Compare to the read header
beq wsCompSect
wsSeekErr:
moveq #seekErr,d0 | Wrong track or side
bra wsDone
bra wsAllDone
/*
* Are we at the right sector? If not, we return with zero flag
* cleared, but d0 = 0.
* Look up the current sector number in the cache.
* If the buffer is dirty ("valid"), write it to disk. If not,
* loop over all the slots and return if all of them are clean.
*
* Alternatively, we could decrement a "dirty sectors" counter here.
*/
wsCompSect:
moveq #0,d1 | Clear register
moveb a4@(o_sector),d1 | get the # of header read
lslw #3,d1 | sizeof cylCacheSlot_t is 8 bytes
movel a6@(o_wslots),a4
tstl a4@(o_valid,d1) | Sector dirty?
bne wsBufDirty
moveb a6@(-5),d1 | Get wanted sector#
cmpb a4@(2),d1 | Compare to the read header
bne wsDone
moveq #maxGCRSectors-1,d2 | Any dirty sectors left?
wsChkDty:
movew d2,d1
lslw #3,d1 | sizeof cylCacheSlot_t is 8 bytes
tstl a4@(o_valid,d1)
bne wsNextSect | Sector dirty?
dbra d2,wsChkDty
bra wsAllDone | We are through with this track.
/*
* Write sync pattern and sector data lead-in 'D5 AA'. The
* missing 'AD' is made up by piping 0x0B through the nibble
@ -988,15 +1048,19 @@ wsCompSect:
* and write subsequent bytes to q6H.
*
* Registers:
* a0 Data register of IWM
* a0 IWM base address (later: data register)
* a1 Via1Base
* a2 IWM handshake register
* a3 data (tags buffer, data buffer)
* a4 Sync pattern, 'toDisk' translation table
* a4 Sync pattern, 'toDisk' translation table
*/
wsBufDirty:
movel _IWMBase,a0
lea a4@(0,d1),a3
movel a3,a6@(-10) | Save ptr to current slot
tstb a0@(q6H) | Enable writing to disk
lea a4@(3),a3 | Point a3 to tags buffer
movel a6@(o_hdr),a4 | Sector header struct
lea a4@(o_Tags),a3 | Point a3 to tags buffer
lea syncPattern,a4
moveb a4@+,a0@(q7H) | Write first sync byte
@ -1052,8 +1116,9 @@ wsLI2:
*
* c) adds up three 8 bit checksums, one for each of the bytes written.
*/
wsSD1:
movel a6@(8),a3 | Start of sector data buffer
wsSD1:
movel a6@(-10),a3 | Get ptr to current slot
movel a3@(o_secbuf),a3 | Get start of sector data buffer
wsData:
addxb d2,d7
@ -1100,6 +1165,7 @@ wsRDY04:
tstb a2@ | IWM ready?
bpl wsRDY04
moveb a4@(0,d2),a0@ | Translate nibble and write
/*
* XXX We have a classic off-by-one error here: the last access
* reaches beyond the data buffer which bombs with memory
@ -1185,6 +1251,22 @@ wsNoErr:
tstb a0@(0x0200) | q7L -- Write OFF
wsDone:
tstb d0 | Any error? Simply retry
bne wsBufInvalid
movel a6@(-10),a4 | Else, get ptr to current slot
clrl a4@(o_valid) | Mark current buffer "clean"
bra wsNextSect
wsBufInvalid:
subqb #1,a6@(-6) | retries
bne wsNextSect
| Sector not found, but
tstb d0 | don't set error code if we
bne wsAllDone | already have one.
moveq #sectNFErr,d0
wsAllDone:
movew a6@(-2),sr | Restore interrupt mask
moveml sp@+,d1-d7/a0-a5
unlk a6
@ -1324,10 +1406,9 @@ driveCmd:
*
* TODO: Poll SCC as long as interrupts are disabled.
*
* Parameters: a0 IWMBase
* a1 VIABase
* a4 sectorHdr_t address
* Parameters: a4 sectorHdr_t address
* Returns: d0 result code
* Uses: d0-d4, a0, a2-a4
*/
readSectHdr:
moveq #3,d4 | Read 3 chars from IWM for sync
@ -1335,6 +1416,7 @@ readSectHdr:
moveq #0,d2 | Clear scratch regs
moveq #0,d1
moveq #0,d0
movel _IWMBase,a0 | IWM base address
tstb a0@(q7L)
lea a0@(q6L),a0 | IWM data register
@ -1360,7 +1442,7 @@ shLeadIn:
moveq #0x03,d4 | is 3 bytes long
shLI1:
moveb a0@,d2 | Get next byte
bpl shLI1
bpl shLI1 | No char at IWM, repeat read
dbra d3,shLI2
moveq #noAdrMkErr,d0 | Can't find an address mark
bra shDone

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $Id: iwm_fdvar.h,v 1.2 1999/02/18 07:50:54 scottr Exp $ */
/* $NetBSD: iwm_fdvar.h,v 1.3 1999/03/27 05:45:20 scottr Exp $ */
/*
* Copyright (c) 1997, 1998 Hauke Fath. All rights reserved.
@ -32,20 +32,20 @@
** Constants
**/
/* Number of attachable drives */
#define IWM_MAX_DRIVE 2
enum {
IWM_MAX_DRIVE = 2, /* Attachable drives */
IWM_GCR_DISK_ZONES = 5, /* Zones on GCR disk */
IWM_MAX_GCR_SECTORS = 12, /* Max. sectors per GCR track */
IWM_MAX_FLOPPY_SECT = 50, /* Larger than the highest sector */
/* number likely to occur */
};
/* Number of zones on GCR disk */
#define IWM_GCR_DISK_ZONES 5
/* Larger than the highest sector number likely */
#define IWM_MAX_FLOPPY_SECT 50
/* Physical track format codes */
enum {
IWM_GCR, /* Apple's Group Code Recording format */
IWM_MFM_DD, /* Standard MFM on DD disk (250 KBit/s) */
IWM_MFM_HD /* Standard MFM on HD disk (500 KBit/s) */
IWM_GCR, /* Apple's Group Code Recording format */
IWM_MFM_DD, /* Standard MFM on DD disk (250 KBit/s) */
IWM_MFM_HD /* Standard MFM on HD disk (500 KBit/s) */
};
/* Drive softc flags */
@ -61,6 +61,12 @@ enum {
IWM_SEEK_VERIFY
};
/* I/O direction */
enum {
IWM_WRITE = 0,
IWM_READ
};
/**
** Data Types
@ -73,15 +79,15 @@ enum {
* tenaciously to the trailing edge of technology...
*/
struct fdInfo {
short heads; /* # of heads the drive has */
short tracks; /* # of tracks per side (cyl's) */
short sectorSize; /* Bytes per sector */
short secPerTrack; /* fake */
short secPerCyl; /* fake */
short secPerDisk; /* # of sectors per __disk__ */
short stepRate; /* in ms (is a software delay) */
short interleave; /* Sector interleave */
short physFormat; /* GCR, MFM DD, MFM HD */
short heads; /* # of heads the drive has */
short tracks; /* # of tracks per side (cyl's) */
short sectorSize; /* Bytes per sector */
short secPerTrack; /* fake */
short secPerCyl; /* fake */
short secPerDisk; /* # of sectors per __disk__ */
short stepRate; /* in ms (is a software delay) */
short interleave; /* Sector interleave */
short physFormat; /* GCR, MFM DD, MFM HD */
char *description;
};
typedef struct fdInfo fdInfo_t;
@ -94,7 +100,7 @@ struct diskPosition {
short oldTrack;
short side;
short sector;
short maxSect; /* Highest sector # for this track */
short maxSect; /* Highest sector # for this track */
};
typedef struct diskPosition diskPosition_t;
@ -102,7 +108,7 @@ typedef struct diskPosition diskPosition_t;
* Zone recording scheme (per disk surface/head)
*/
struct diskZone {
short tracks; /* # of tracks per zone */
short tracks; /* # of tracks per zone */
short sectPerTrack;
short firstBlock;
short lastBlock;
@ -113,8 +119,8 @@ typedef struct diskZone diskZone_t;
* Arguments passed between iwmAttach() and the fd probe routines.
*/
struct iwmAttachArgs {
fdInfo_t *driveType; /* Default drive parameters */
short unit; /* Current drive # */
fdInfo_t *driveType; /* Default drive parameters */
short unit; /* Current drive # */
};
typedef struct iwmAttachArgs iwmAttachArgs_t;
@ -124,25 +130,43 @@ typedef struct iwmAttachArgs iwmAttachArgs_t;
*
*/
struct fd_softc {
struct device devInfo; /* generic device info */
struct disk diskInfo; /* generic disk info */
struct buf bufQueue; /* queue of buf's */
struct device devInfo; /* generic device info */
struct disk diskInfo; /* generic disk info */
struct buf bufQueue; /* queue of buf's */
/* private stuff here */
daddr_t startBlk; /* Starting block # */
int bytesLeft; /* Bytes left to transfer */
int bytesDone; /* Bytes transferred */
/* errors & retries in current I/O job */
int iwmErr; /* Last IO error */
int ioRetries;
int seekRetries;
int sectRetries;
int verifyRetries;
/* hardware info */
int drvFlags; /* Copy of drive flags */
short stepDirection; /* Current step direction */
diskPosition_t pos; /* Physical position on disk */
/* drive info */
short unit; /* Drive # as seen by IWM */
short partition; /* "Partition" info {a,b,c,...} */
fdInfo_t *defaultType; /* default floppy format */
fdInfo_t *currentType; /* current floppy format */
int state; /* XXX */
int drvFlags; /* Copy of drive flags */
short unit; /* Drive # as seen by IWM */
short partition; /* "Partition" info {a,b,c,...} */
fdInfo_t *defaultType; /* default floppy format */
fdInfo_t *currentType; /* current floppy format */
int state; /* XXX */
void *trackBuf; /* Pointer to track buffer */
short stepDirection; /* Current step direction */
diskPosition_t pos; /* Physical position on disk */
int writeLabel; /* Write access to disklabel? */
/* data transfer info */
int ioDirection; /* Read/write */
daddr_t startBlk; /* Starting block # */
int bytesLeft; /* Bytes left to transfer */
int bytesDone; /* Bytes transferred */
caddr_t current_buffer; /* target of current data transfer */
unsigned char *cbuf; /* ptr to cylinder cache */
int cachedSide; /* Which head is cached? */
cylCacheSlot_t r_slots[IWM_MAX_GCR_SECTORS];
cylCacheSlot_t w_slots[IWM_MAX_GCR_SECTORS];
int writeLabel; /* Write access to disklabel? */
sectorHdr_t sHdr; /* current sector header */
};
typedef struct fd_softc fd_softc_t;
@ -152,15 +176,15 @@ typedef struct fd_softc fd_softc_t;
* SWIM/MFM mode may have some state to keep here.
*/
struct iwm_softc {
struct device devInfo; /* generic device info */
int drives; /* # of attached fd's */
fd_softc_t *fd[IWM_MAX_DRIVE]; /* ptrs to children */
struct device devInfo; /* generic device info */
int drives; /* # of attached fd's */
fd_softc_t *fd[IWM_MAX_DRIVE]; /* ptrs to children */
int state; /* make that an enum? */
u_char modeReg; /* Copy of IWM mode register */
short maxRetries; /* I/O retries */
int state; /* make that an enum? */
u_char modeReg; /* Copy of IWM mode register */
short maxRetries; /* I/O retries */
int errors;
int underruns; /* data not delivered in time */
int underruns; /* data not delivered in time */
};
typedef struct iwm_softc iwm_softc_t;
@ -193,27 +217,32 @@ dev_type_size(fdsize);
dev_type_dump(fddump);
int iwmSelectDrive __P((int drive));
int iwmSelectSide __P((int side));
int iwmInit __P((void));
int iwmCheckDrive __P((int32_t drive));
int iwmSelectDrive __P((int32_t drive));
int iwmSelectSide __P((int32_t side));
int iwmTrack00 __P((void));
int iwmSeek __P((int steps));
int iwmSeek __P((int32_t steps));
int iwmReadSector __P((caddr_t buf, sectorHdr_t *hdr));
int iwmWriteSector __P((caddr_t buf, sectorHdr_t *hdr));
int iwmReadSector __P((sectorHdr_t *hdr, cylCacheSlot_t *r_slots,
caddr_t buf));
int iwmWriteSector __P((sectorHdr_t *hdr, cylCacheSlot_t *w_slots));
int iwmDiskEject __P((int drive)); /* drive = [0..1] */
int iwmMotor __P((int drive, int onOff)); /* on(1)/off(0) */
int iwmDiskEject __P((int32_t drive)); /* drive = [0..1] */
int iwmMotor __P((int32_t drive, int32_t onOff)); /* on(1)/off(0) */
/*
* Debugging only
*/
int iwmQueryDrvFlag __P((int drive, int reg)); /* reg = [0..15] */
int iwmQueryDrvFlag __P((int32_t drive, int32_t reg)); /* reg = [0..15] */
/* Make sure we run at splhigh when calling! */
int iwmReadSectHdr __P((sectorHdr_t *hdr));
int iwmReadRawSector __P((int ID, caddr_t buf));
int iwmWriteRawSector __P((int ID, caddr_t buf));
int iwmReadRawTrack __P((int mode, caddr_t buf));
#if 0 /* XXX not yet */
int iwmReadRawSector __P((int32_t ID, caddr_t buf));
int iwmWriteRawSector __P((int32_t ID, caddr_t buf));
int iwmReadRawTrack __P((int32_t mode, caddr_t buf));
#endif
#endif /* _MAC68K_FDVAR_H */

View File

@ -1,4 +1,4 @@
/* $Id: iwm_regs.s,v 1.1 1999/02/18 07:38:26 scottr Exp $ */
/* $NetBSD: iwm_regs.s,v 1.2 1999/03/27 05:45:20 scottr Exp $ */
/*
* Copyright (c) 1996-98 Hauke Fath. All rights reserved.

View File

@ -1,7 +1,7 @@
/* $Id: iwmreg.h,v 1.2 1999/02/18 07:50:54 scottr Exp $ */
/* $NetBSD: iwmreg.h,v 1.3 1999/03/27 05:45:20 scottr Exp $ */
/*
* Copyright (c) 1996-98 Hauke Fath. All rights reserved.
* Copyright (c) 1996-99 Hauke Fath. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -32,13 +32,14 @@
* iwmreg.h -- Interface declarations for iwm.
*/
#ifndef _LOCORE
/*
* Configuration
*/
int iwmInit(void);
/* Virtual Drive flags register */
enum dFlags {
enum {
IWM_DS_DISK = 0x01,
IWM_NO_DISK = 0x02,
IWM_MOTOR_OFF = 0x04,
@ -46,12 +47,12 @@ enum dFlags {
IWM_DD_DISK = 0x10,
IWM_NO_DRIVE = 0x80000000
};
int iwmCheckDrive(int drive);
/*
* Access
*/
enum dErrors {
enum {
noErr = 0, /* All went well */
noDriveErr = -64, /* Drive not installed */
offLinErr = -65, /* R/W requested for an offline drive */
noNybErr = -66, /* Disk is probably blank */
@ -79,18 +80,189 @@ enum dErrors {
fmt2Err = -83, /* Can't get enough sync */
verErr = -84 /* Track failed to verify */
};
typedef enum dErrors dErrors_t;
/*
* This is byte-aligned (just in case anyone's interested...)
*/
#define IWM_TAG_SIZE 20 /* That's what "SonyEqu.a" says */
/* Buffer for sector header data */
struct sectorHdr {
u_int8_t side;
u_int8_t track;
u_int8_t sector;
u_int8_t Tags[13]; /* XXX Looks like it, although IM */
/* specifies 12 tag bytes */
u_int8_t Tags[IWM_TAG_SIZE];
};
typedef struct sectorHdr sectorHdr_t;
/*
* Cylinder cache data structure
* Cyl buffer is allocated in fdopen() and deallocated in fdclose().
*
* The "valid" flag is overloaded as "dirty" flag when writing
* to disk.
*/
struct cylCacheSlot {
unsigned char *secbuf; /* ptr to one sector buffer */
int32_t valid; /* content valid for cur. cylinder? */
};
typedef struct cylCacheSlot cylCacheSlot_t;
#else /* _LOCORE */
/*
* Assembler equates for IWM, kept here to ensure consistency.
* Modelled after <sys/disklabel.h>
*/
/*
* Offsets into data structures
*/
/* sectorHdr_t */
.equ o_side, 0
.equ o_track, 1
.equ o_sector, 2
.equ o_Tags, 3
/* cylCacheSlot_t */
.equ o_secbuf, 0
.equ o_valid, 4
/*
* Parameter (a6) offsets from <mac68k/obio/iwm_fdvar.h>
*
* int iwmReadSector __P((sectorHdr_t *hdr, cylCacheSlot_t *r_slots,
* caddr_t buf))
* int iwmWriteSector __P((sectorHdr_t *hdr, cylCacheSlot_t *w_slots))
*/
.equ o_hdr, 8
.equ o_rslots, 12
.equ o_wslots, 12
.equ o_buf, 16
/*
* I/O base addresses
*/
.global _Via1Base /* in machdep.c */
.global _IOBase
.global _IWMBase /* in iwm_fd.c */
/*
* Offsets from IWM base address
* Lines are set by any memory access to corresponding address (IM III-34/-44).
* The SWIM has actual registers at these addresses, so writing to them
* in IWM mode is a no-no.
*/
.equ ph0L, 0x0000 /* CA0 off (0) */
.equ ph0H, 0x0200 /* CA0 on (1) */
.equ ph1L, 0x0400 /* CA1 off (0) */
.equ ph1H, 0x0600 /* CA1 on (1) */
.equ ph2L, 0x0800 /* CA2 off (0) */
.equ ph2H, 0x0A00 /* CA2 on (1) */
.equ ph3L, 0x0C00 /* LSTRB off (low) */
.equ ph3H, 0x0E00 /* LSTRB on (high) */
.equ mtrOff, 0x1000 /* disk enable off */
.equ mtrOn, 0x1200 /* disk enable on */
.equ intDrive, 0x1400 /* select internal drive */
.equ extDrive, 0x1600 /* select external drive */
.equ q6L, 0x1800 /* Q6 off */
.equ q6H, 0x1A00 /* Q6 on */
.equ q7L, 0x1C00 /* Q7 off */
.equ q7H, 0x1E00 /* Q7 on */
/*
* VIA Disk SEL line
*/
.equ vBufA, 0x1E00 /* Offset from vBase to register A */
/* (IM III-43) */
.equ vHeadSel, 5 /* Multi-purpose line (SEL) */
.equ vHeadSelMask, 0x0020 /* Corresponding bit mask */
/*
* Disk registers
* bit 0 - CA2, bit 1 - SEL, bit 2 - CA0, bit 3 - CA1 IM III name
*/
/* Status */
.equ stepDirection, 0x0000 /* Direction of next head step */
/* 0 = in, 1 = out (DIRTN) */
.equ rdDataFrom0, 0x0001 /* Set up drive to read data from */
/* head 0 (RDDATA0) */
.equ diskInserted, 0x0002 /* Disk inserted */
/* 0 = yes, 1 = no (CSTIN) */
.equ rdDataFrom1, 0x0003 /* Set up drive to read data from */
/* head 1 (RDDATA1) */
.equ stillStepping, 0x0004 /* Drive is still stepping */
/* 0 = yes, 1 = no (STEP) */
.equ writeProtected, 0x0006 /* Disk is locked */
/* 0 = yes, 1 = no (WRTPRT) */
.equ drvMotorState, 0x0008 /* Drive motor is on */
/* 0 = yes, 1 = no (MOTORON) */
.equ singleSided, 0x0009 /* Drive is single-sided */
/* 0 = yes, 1 = no (SIDES) */
.equ atTrack00, 0x000A /* Head is at track 00 */
/* 0 = yes, 1 = no (TK0) */
.equ headLoaded, 0x000B /* Head loaded, drive is ready */
/* 0 = yes, 1 = no () */
.equ drvInstalled, 0x000D /* Disk drive installed */
/* 0 = yes, 1 = no () */
.equ tachPulse, 0x000E /* Tachometer pulse (60 /rev.) */
/* 0 = yes, 1 = no (TACH) */
.equ diskIsHD, 0x000F /* HD disk detected */
/* 0 = yes, 1 = no (DRVIN) */
/* Commands */
.equ stepInCmd, 0x0000 /* Head step direction in (DIRTN) */
.equ stepOutCmd, 0x0001 /* Head step direction out (DIRTN+1) */
.equ doStepCmd, 0x0004 /* Step head (STEP) */
.equ motorOnCmd, 0x0008 /* Switch drive motor on (MOTORON) */
.equ motorOffCmd, 0x0009 /* Switch drive motor off (MOTOROFF) */
.equ ejectDiskCmd, 0x000D /* Eject disk from drive (EJECT) */
/*
* Low level disk errors
* For simplicity, they are given the MacOS names and numbers.
*/
.equ noErr, 0 /* All went well */
.equ noDriveErr, -64 /* Drive not installed */
.equ offLinErr, -65 /* R/W requested for an offline drive */
.equ noNybErr, -66 /* Disk is probably blank */
.equ noAdrMkErr, -67 /* Can't find an address mark */
.equ dataVerErr, -68 /* Read verify compare failed */
.equ badCkSmErr, -69 /* Bad address mark checksum */
.equ badBtSlpErr, -70 /* Bad address mark (no lead-out) */
.equ noDtaMkErr, -71 /* Could not find a data mark */
.equ badDCkSum, -72 /* Bad data mark checksum */
.equ badDBtSlp, -73 /* One of the data mark bit slip */
/* nibbles was incorrect. */
.equ wrUnderRun, -74 /* Could not write fast enough to */
/* keep up with the IWM */
.equ cantStepErr, -75 /* Step handshake failed during seek */
.equ tk0BadErr, -76 /* Track 00 sensor does not change */
/* during head calibration */
.equ initIWMErr, -77 /* Unable to initialize IWM */
.equ twoSideErr, -78 /* Tried to access a double-sided disk */
/* on a single-sided drive (400K drive) */
.equ spAdjErr, -79 /* Can't adjust drive speed (400K drive) */
.equ seekErr, -80 /* Wrong track number read in a */
/* sector's address field */
.equ sectNFErr, -81 /* Sector number never found on a track */
.equ fmt1Err, -82 /* Can't find sector 0 after */
/* track format */
.equ fmt2Err, -83 /* Can't get enough sync */
.equ verErr, -84 /* Track failed to verify */
/*
* Misc constants
*/
.equ iwmMode, 0x17 /* SWIM switch */
.equ maxGCRSectors, 12 /* Max. sectors per track for GCR */
#endif /* _LOCORE */
#endif /* _MAC68K_IWMREG_H */