Added head load/unload with unload timer

This commit is contained in:
Patrick Linstruth 2019-12-05 19:40:29 -08:00
parent 6efda7cbea
commit 91b6807499

View file

@ -42,6 +42,8 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ
#define TARBELL_BYTES_PER_TRACK ((TARBELL_SECTORS_PER_TRACK * 186) + 73 + 247)
#define TARBELL_TRACKS 77
#define TARBELL_CAPACITY (256256) /* Default Tarbell Disk Capacity */
#define TARBELL_ROTATION_MS 50
#define TARBELL_HEAD_TIMEOUT (TARBELL_ROTATION_MS * 2)
#define TARBELL_PROM_SIZE 32
#define TARBELL_PROM_MASK (TARBELL_PROM_SIZE-1)
@ -78,6 +80,9 @@ typedef struct {
uint8 writeActive; /* Write Active */
uint8 writeTrkActive; /* Write Track Active */
uint8 addrActive; /* Address Active */
uint8 driveNotReady; /* Drive Not Ready */
uint8 headLoaded; /* Head Loaded */
uint32 headUnlTime; /* Time to unload head */
} FD1771_REG;
#define FD1771_STAT_NOTREADY 0x80
@ -175,10 +180,12 @@ static uint32 stepCleared = TRUE; /* true when step bit has returned to zero *
/* Local function prototypes */
static t_stat tarbell_reset(DEVICE *tarbell_dev);
static t_stat tarbell_svc(UNIT *uptr);
static t_stat tarbell_attach(UNIT *uptr, CONST char *cptr);
static t_stat tarbell_detach(UNIT *uptr);
static t_stat tarbell_boot(int32 unitno, DEVICE *dptr);
static t_stat tarbell_set_prom(UNIT *uptr, int32 value, CONST char *cptr, void *desc);
static void TARBELL_HeadLoad(UNIT *uptr, FD1771_REG *pFD1771, uint8 load);
static uint8 TARBELL_Read(const uint32 Addr);
static uint8 TARBELL_Write(const uint32 Addr, int32 data);
static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 data);
@ -192,10 +199,10 @@ static int32 tarbelldev(const int32 Addr, const int32 rw, const int32 data);
static int32 tarbellprom(const int32 Addr, const int32 rw, const int32 data);
static UNIT tarbell_unit[TARBELL_MAX_DRIVES] = {
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY) }
{ UDATA (tarbell_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY), 10000 },
{ UDATA (tarbell_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY), 10000 },
{ UDATA (tarbell_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY), 10000 },
{ UDATA (tarbell_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TARBELL_CAPACITY), 10000 }
};
static REG tarbell_reg[] = {
@ -326,6 +333,27 @@ t_stat tarbell_reset(DEVICE *dptr)
pInfo->FD1771.writeActive = FALSE;
pInfo->FD1771.writeTrkActive = FALSE;
pInfo->FD1771.addrActive = FALSE;
pInfo->FD1771.headLoaded = FALSE;
pInfo->FD1771.driveNotReady = TRUE;
return SCPE_OK;
}
static t_stat tarbell_svc(UNIT *uptr)
{
uint32 now;
/*
** Get current msec time
*/
now = sim_os_msec();
if (now < tarbell_info->FD1771.headUnlTime) {
sim_activate(uptr, 100000); /* restart timer */
}
else if (tarbell_info->FD1771.headLoaded == TRUE) {
TARBELL_HeadLoad(uptr, &tarbell_info->FD1771, FALSE);
}
return SCPE_OK;
}
@ -383,6 +411,11 @@ t_stat tarbell_attach(UNIT *uptr, CONST char *cptr)
uptr->capac);
}
/*
** Clear Not Ready Flag
*/
tarbell_info->FD1771.driveNotReady = FALSE;
return SCPE_OK;
}
@ -417,6 +450,11 @@ t_stat tarbell_detach(UNIT *uptr)
sim_printf(TARBELL_SNAME "%d detached." NLP, i);
}
/*
** Set Not Ready Flag
*/
tarbell_info->FD1771.driveNotReady = TRUE;
return SCPE_OK;
}
@ -479,6 +517,26 @@ static uint32 calculate_tarbell_sec_offset(uint8 track, uint8 sector)
return (offset);
}
static void TARBELL_HeadLoad(UNIT *uptr, FD1771_REG *pFD1771, uint8 load)
{
sim_cancel(uptr); /* cancel timer */
if (load) {
pFD1771->headUnlTime = sim_os_msec() + TARBELL_HEAD_TIMEOUT;
sim_activate(uptr, 100000); /* activate timer */
}
if (load == TRUE && pFD1771->headLoaded == FALSE) {
sim_debug(STATUS_MSG, &tarbell_dev, TARBELL_SNAME ": Head Loaded." NLP);
}
if (load == FALSE && pFD1771->headLoaded == TRUE) {
sim_debug(STATUS_MSG, &tarbell_dev, TARBELL_SNAME ": Head Unloaded." NLP);
}
tarbell_info->FD1771.headLoaded = load;
}
static uint8 TARBELL_Read(const uint32 Addr)
{
uint8 cData;
@ -521,6 +579,7 @@ static uint8 TARBELL_Read(const uint32 Addr)
pFD1771->status |= FD1771_STAT_DRQ; /* Another byte is ready */
}
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
else if (pFD1771->addrActive) {
/* Store byte in DATA register */
@ -539,6 +598,8 @@ static uint8 TARBELL_Read(const uint32 Addr)
else {
pFD1771->status |= FD1771_STAT_DRQ; /* Another byte is ready */
}
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
cData = pFD1771->data;
@ -607,6 +668,7 @@ static uint8 TARBELL_Write(const uint32 Addr, const int32 Data)
pFD1771->status |= FD1771_STAT_DRQ; /* Ready for another byte */
}
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
else if (pFD1771->writeTrkActive) {
@ -649,7 +711,7 @@ static uint8 TARBELL_Write(const uint32 Addr, const int32 Data)
sim_debug(WR_DATA_MSG, &tarbell_dev, TARBELL_SNAME ": WRITE TRACK track=%03d sector=%03d trkcount=%d datacount=%d data=%02X status=%02X" NLP, pFD1771->track, pFD1771->sector, pFD1771->trkCount, pFD1771->dataCount, pFD1771->data, pFD1771->status);
}
// showregs(pFD1771);
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
DBG_PRINT(("TARBELL: WRITE DATA REG %02X" NLP, Data));
@ -785,6 +847,10 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": RESTORE track=%03d" NLP, pFD1771->track);
if (Data & TARBELL_FLAG_H) {
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
pFD1771->status &= ~FD1771_STAT_SEEKERROR;
pFD1771->status &= ~FD1771_STAT_BUSY;
pFD1771->status &= ~FD1771_STAT_DRQ;
@ -807,6 +873,10 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": SEEK ERR track=%03d" NLP, newTrack);
}
if (Data & TARBELL_FLAG_H) {
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
pFD1771->status &= ~FD1771_STAT_BUSY;
pFD1771->status &= ~FD1771_STAT_DRQ;
pFD1771->intrq = TRUE;
@ -819,7 +889,9 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
newTrack = pFD1771->track + pFD1771->stepDir;
if (newTrack < TARBELL_TRACKS-1) {
pFD1771->track = newTrack;
if (Data & TARBELL_FLAG_U) {
pFD1771->track = newTrack;
}
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEP track=%03d" NLP, pFD1771->track);
}
else {
@ -827,6 +899,10 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEP ERR track=%03d" NLP, newTrack);
}
if (Data & TARBELL_FLAG_H) {
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
pFD1771->status &= ~FD1771_STAT_BUSY;
pFD1771->status &= ~FD1771_STAT_DRQ;
pFD1771->intrq = TRUE;
@ -837,7 +913,9 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
pFD1771->status &= ~FD1771_STAT_SEEKERROR;
if (pFD1771->track < TARBELL_TRACKS) {
pFD1771->track++;
if (Data & TARBELL_FLAG_U) {
pFD1771->track++;
}
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPIN track=%03d" NLP, pFD1771->track);
}
else {
@ -845,6 +923,10 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPIN ERR track=%03d" NLP, pFD1771->track+1);
}
if (Data & TARBELL_FLAG_H) {
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
pFD1771->stepDir = 1;
pFD1771->status &= ~FD1771_STAT_BUSY;
pFD1771->status &= ~FD1771_STAT_DRQ;
@ -856,7 +938,9 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
pFD1771->status &= ~FD1771_STAT_SEEKERROR;
if (pFD1771->track > 0) {
pFD1771->track--;
if (Data & TARBELL_FLAG_U) {
pFD1771->track--;
}
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPOUT track=%03d" NLP, pFD1771->track);
}
else {
@ -864,6 +948,10 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
sim_debug(SEEK_MSG, &tarbell_dev, TARBELL_SNAME ": STEPOUT ERR track=%03d" NLP, pFD1771->track-1);
}
if (Data & TARBELL_FLAG_H) {
TARBELL_HeadLoad(uptr, pFD1771, TRUE);
}
pFD1771->stepDir = -1;
pFD1771->status &= ~FD1771_STAT_BUSY;
pFD1771->status &= ~FD1771_STAT_DRQ;
@ -972,6 +1060,8 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
/* Update Status Register */
/**************************/
pFD1771->status |= (pFD1771->driveNotReady) ? FD1771_STAT_NOTREADY : 0x00;
switch(pFD1771->command) {
case TARBELL_CMD_RESTORE:
case TARBELL_CMD_SEEK:
@ -984,12 +1074,12 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
case TARBELL_CMD_FORCE_INTR:
if (statusUpdate) {
pFD1771->status &= ~FD1771_STAT_WRITEPROT;
pFD1771->status &= ~FD1771_STAT_HEADLOAD;
pFD1771->status &= ~FD1771_STAT_CRCERROR;
pFD1771->status &= ~FD1771_STAT_TRACK0;
pFD1771->status |= ((uptr->flags & UNIT_TARBELL_WPROTECT) || tarbell_info->writeProtect) ? FD1771_STAT_WRITEPROT : 0x00;
pFD1771->status |= (pFD1771->track) ? 0x00 : FD1771_STAT_TRACK0;
pFD1771->status |= FD1771_STAT_INDEX;
pFD1771->status |= (pFD1771->headLoaded) ? FD1771_STAT_HEADLOAD : 0x00;
pFD1771->status |= FD1771_STAT_INDEX; /* Always set Index Flag if Drive Ready */
}
break;
@ -1008,21 +1098,26 @@ static uint8 TARBELL_Command(UNIT *uptr, FD1771_REG *pFD1771, const int32 Data)
break;
case TARBELL_CMD_READ_ADDRESS:
pFD1771->status &= ~0x20;
pFD1771->status &= ~0x40;
pFD1771->status &= ~FD1771_STAT_LOSTDATA;
pFD1771->status &= ~FD1771_STAT_NOTFOUND;
pFD1771->status &= ~FD1771_STAT_CRCERROR;
break;
case TARBELL_CMD_READ_TRACK:
pFD1771->status &= ~0x08;
pFD1771->status &= ~0x10;
pFD1771->status &= ~0x20;
pFD1771->status &= ~0x40;
pFD1771->status &= ~FD1771_STAT_LOSTDATA;
pFD1771->status &= ~FD1771_STAT_NOTFOUND;
pFD1771->status &= ~FD1771_STAT_CRCERROR;
break;
case TARBELL_CMD_WRITE_TRACK:
pFD1771->status &= ~0x08;
pFD1771->status &= ~0x10;
pFD1771->status &= ~FD1771_STAT_WRITEPROT;
pFD1771->status &= ~FD1771_STAT_LOSTDATA;
pFD1771->status &= ~FD1771_STAT_NOTFOUND;
pFD1771->status &= ~FD1771_STAT_WRITEFAULT;
pFD1771->status |= ((uptr->flags & UNIT_TARBELL_WPROTECT) || tarbell_info->writeProtect) ? FD1771_STAT_WRITEPROT : 0x00;
break;