1
0
mirror of https://github.com/open-simh/simh.git synced 2026-04-25 03:44:58 +00:00

Notes For V3.8

The makefile now works for Linux and most Unix's. Howevr, for Solaris
and MacOS, you must first export the OSTYPE environment variable:

> export OSTYPE
> make

Otherwise, you will get build errors.

1. New Features

1.1 3.8-0

1.1.1 SCP and Libraries

- BREAK, NOBREAK, and SHOW BREAK with no argument will set, clear, and
  show (respectively) a breakpoint at the current PC.

1.2 GRI

- Added support for the GRI-99 processor.

1.3 HP2100

- Added support for the BACI terminal interface.
- Added support for RTE OS/VMA/EMA, SIGNAL, VIS firmware extensions.

1.4 Nova

- Added support for 64KW memory (implemented in third-party CPU's).

1.5 PDP-11

- Added support for DC11, RC11, KE11A, KG11A.
- Added modem control support for DL11.
- Added ASCII character support for all 8b devices.

2. Bugs Fixed

Please see the revision history on http://simh.trailing-edge.com or
in the source module sim_rev.h.
This commit is contained in:
Bob Supnik
2008-06-24 14:21:00 -07:00
committed by Mark Pizzolato
parent 3cb7c60d5d
commit 59aa4a73b1
136 changed files with 57039 additions and 10915 deletions

View File

@@ -1,6 +1,6 @@
/* nova_dkp.c: NOVA moving head disk simulator
Copyright (c) 1993-2005, Robert M. Supnik
Copyright (c) 1993-2008, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,23 @@
dkp moving head disk
04-Jul-04 BKR device name changed to DG's DKP from DEC's DP,
DEV_SET/CLR/INTR macro use started,
fixed 'P' pulse code and secret quirks,
added 6097 diag and size support,
fixed losing unit drive type during unit change,
tightened sector size determination calculations,
controller DONE flag handling fixed,
fixed cylinder overflow test error,
seek error code fixed,
restructured dkp_go() and dkp_svc() routines
(for known future fixes needed),
fixed DIA status calculation,
fixed DKP read/write loop to properly emulate DG cylinder and sector overflows,
added trace facility,
changed 'stime' calculation to force delay time if no cylinders are crossed
(this fixes some DG code that assumes disk seek takes some time),
fixed boot code to match DG hardware standard
04-Jan-04 RMS Changed attach routine to use sim_fsize
28-Nov-03 CEO Boot from DP now puts device address in SR
24-Nov-03 CEO Added support for disk sizing on 6099/6103
@@ -110,15 +127,35 @@
#define FCCY_SEEK 2
#define FCCY_RECAL 3
#define FCCY_FLAGS 0174000 /* flags */
#define GET_CMD(x,dt) ((drv_tab[dt].newf)? \
(((x) >> FCCY_V_NCMD) & FCCY_M_NCMD): \
(((x) >> FCCY_V_OCMD) & FCCY_M_OCMD) )
#define SET_CMD(x,dt) dkp_fccy = (dkp_fccy & ((drv_tab[dt].newf)? \
(FCCY_M_NCMD << FCCY_V_NCMD) : (FCCY_M_OCMD << FCCY_V_OCMD))) | \
((drv_tab[dt].newf)? \
(((x) & FCCY_M_NCMD) << FCCY_V_NCMD): \
(((x) & FCCY_M_OCMD) << FCCY_V_OCMD) )
#define GET_CYL(x,dt) ((drv_tab[dt].newf)? \
(((x) >> FCCY_V_NCYL) & FCCY_M_NCYL): \
((((x) >> FCCY_V_OCYL) & FCCY_M_OCYL) | \
((dt != TYPE_D44)? 0: \
(((x) & FCCY_OCEX) >> (FCCY_V_OCEX - FCCY_V_OCMD)))) )
/* (Warning: no sector or surface masking is done!) */
#define DKP_UPDATE_USSC( type, count, surf, sect ) \
dkp_ussc = (dkp_ussc & USSC_UNIT) \
| ((dkp_ussc + count) & USSC_M_COUNT) \
| ((drv_tab[dtype].newf)? \
((surf << USSC_V_NSURFACE) | (sect << USSC_V_NSECTOR)): \
((surf << USSC_V_OSURFACE) | (sect << USSC_V_OSECTOR)) \
);
/* Status */
#define STA_ERR 0000001 /* error */
@@ -154,14 +191,17 @@
floppy 8 1 77 no
DS/DD floppy 16 2 77 yes
(6097 "quad floppy")
Diablo 31 12 2 203 no
6225 20 2 245 yes
Century 111 6 10 203 no
4048 (same as Century 111)
Diablo 44 12 4 408 no
6099 32 4 192 yes
6227 20 6 245 yes
6070 24 4 408 yes
Century 114 12 20 203 no
4057 (same as Century 114)
6103 32 8 192 yes
4231 23 19 411 yes
@@ -178,6 +218,7 @@
#define NFMT_FLP FALSE
#define TYPE_DSDD 1
#define TYPE_6097 TYPE_DSDD
#define SECT_DSDD 16
#define SURF_DSDD 2
#define CYL_DSDD 77
@@ -278,9 +319,20 @@ struct drvtyp drv_tab[] = {
{ 0 }
};
#define DKP_TRACE(x) (dkp_trace & (1<<(x)))
#define DKP_TRACE_FP stderr
/* current trace bit use (bit 0 = LSB)
0 I/O instructions
1 pre-seek/read/write event setup
2 seek events
3 read/write events
4 post read/write events
*/
extern uint16 M[];
extern UNIT cpu_unit;
extern int32 int_req, dev_busy, dev_done, dev_disable;
extern int32 saved_PC, SR, AMASK;
int32 dkp_ma = 0; /* memory address */
int32 dkp_map = 0; /* DCH map 0=A 3=B */
@@ -291,13 +343,15 @@ int32 dkp_swait = 100; /* seek latency */
int32 dkp_rwait = 100; /* rotate latency */
int32 dkp_diagmode = 0; /* diagnostic mode */
int32 dkp_trace = 0 ;
DEVICE dkp_dev;
int32 dkp (int32 pulse, int32 code, int32 AC);
t_stat dkp_svc (UNIT *uptr);
t_stat dkp_reset (DEVICE *dptr);
t_stat dkp_boot (int32 unitno, DEVICE *dptr);
t_stat dkp_attach (UNIT *uptr, char *cptr);
t_stat dkp_go (void);
t_stat dkp_go ( int32 pulse );
t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
/* DKP data structures
@@ -330,7 +384,8 @@ REG dkp_reg[] = {
{ FLDATA (BUSY, dev_busy, INT_V_DKP) },
{ FLDATA (DONE, dev_done, INT_V_DKP) },
{ FLDATA (DISABLE, dev_disable, INT_V_DKP) },
{ FLDATA (DIAG, dkp_diagmode, 0) },
{ FLDATA (DIAG, dkp_diagmode, 0) },
{ DRDATA (TRACE, dkp_trace, 32) },
{ ORDATA (MAP, dkp_map, 2) },
{ DRDATA (STIME, dkp_swait, 24), PV_LEFT },
{ DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
@@ -438,13 +493,14 @@ MTAB dkp_mod[] = {
};
DEVICE dkp_dev = {
"DP", dkp_unit, dkp_reg, dkp_mod,
"DKP", dkp_unit, dkp_reg, dkp_mod,
DKP_NUMDR, 8, 30, 1, 8, 16,
NULL, NULL, &dkp_reset,
&dkp_boot, &dkp_attach, NULL,
&dkp_dib, DEV_DISABLE
};
/* IOT routine */
int32 dkp (int32 pulse, int32 code, int32 AC)
@@ -456,14 +512,26 @@ rval = 0;
uptr = dkp_dev.units + GET_UNIT (dkp_ussc); /* select unit */
dtype = GET_DTYPE (uptr->flags); /* get drive type */
if ( DKP_TRACE(0) )
{
static char * f[8] =
{ "NIO", "DIA", "DOA", "DIB", "DOB", "DIC", "DOC", "SKP" } ;
static char * s[4] =
{ " ", "S", "C", "P" } ;
printf( " [DKP %s%s %06o ", f[code & 0x07], s[pulse & 0x03], (AC & 0xFFFF) ) ;
}
switch (code) { /* decode IR<5:7> */
case ioDIA: /* DIA */
dkp_sta = dkp_sta & ~STA_DYN; /* clear dynamic */
if (uptr->flags & UNIT_ATT) dkp_sta = dkp_sta | STA_DRDY;
dkp_sta = dkp_sta & (~STA_DRDY) ; /* keep error flags */
if (uptr->flags & UNIT_ATT) /* update ready */
dkp_sta = dkp_sta | STA_DRDY;
if (uptr->CYL >= drv_tab[dtype].cyl)
dkp_sta = dkp_sta | STA_CYL; /* bad cylinder? */
if (dkp_sta & STA_EFLGS) dkp_sta = dkp_sta | STA_ERR;
if (dkp_sta & STA_EFLGS)
dkp_sta = dkp_sta | STA_ERR;
rval = dkp_sta;
break;
@@ -474,20 +542,25 @@ switch (code) { /* decode IR<5:7> */
dkp_fccy = AC; /* save cmd, cyl */
dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS);
}
if ((dkp_sta & STA_DFLGS) == 0) /* done flags = 0? */
dev_done = dev_done & ~INT_DKP; /* clear intr */
DEV_CLR_DONE( INT_DKP ) ; /* assume done flags 0 */
if ( dkp_sta & STA_DFLGS ) /* done flags = 0? */
DEV_SET_DONE( INT_DKP ) ; /* nope - set done */
DEV_UPDATE_INTR ; /* update intr */
break;
case ioDIB: /* DIB */
rval = dkp_ma; /* return buf addr */
rval = dkp_ma & 077777 ; /* return buf addr */
/* with B0 clear (no DCH B map support) */
break;
case ioDOB: /* DOB */
if ((dev_busy & INT_DKP) == 0) {
dkp_ma = AC & (drv_tab[dtype].newf? DMASK: AMASK);
if (AC & 0100000) dkp_map = 3; /* high bit is map */
else dkp_map = 0;
}
if (AC & 0100000)
dkp_map = 3; /* high bit is map */
else
dkp_map = 0;
}
break;
case ioDIC: /* DIC */
@@ -495,63 +568,97 @@ switch (code) { /* decode IR<5:7> */
break;
case ioDOC: /* DOC */
if ((dev_busy & INT_DKP) == 0) dkp_ussc = AC; /* save unit, sect */
if (((dtype == TYPE_6099) || /* for 6099 and 6103 */
(dtype == TYPE_6103)) && /* if data<0> set, */
AC & 010000) dkp_diagmode = 1; /* set diagnostic mode */
if ((dev_busy & INT_DKP) == 0) /* if device is not busy */
dkp_ussc = AC ; /* save unit, sect */
if (((dtype == TYPE_6099) || /* (BKR: don't forget 6097) */
(dtype == TYPE_6097) || /* for 6099 and 6103 */
(dtype == TYPE_6103)) && /* if data<0> set, */
(AC & 010000) )
dkp_diagmode = 1; /* set diagnostic mode */
break;
} /* end switch code */
u = GET_UNIT(dkp_ussc); /* select unit */
u = GET_UNIT(dkp_ussc); /* update current unit */
uptr = dkp_dev.units + u ; /* select unit */
dtype = GET_DTYPE (uptr->flags); /* get drive type */
if ( DKP_TRACE(0) )
{
if ( code & 1 )
printf( " [%06o] ", (rval & 0xFFFF) ) ;
printf( "] \n" ) ;
}
switch (pulse) { /* decode IR<8:9> */
case iopS: /* start */
dev_busy = dev_busy | INT_DKP; /* set busy */
dev_done = dev_done & ~INT_DKP; /* clear done */
int_req = int_req & ~INT_DKP; /* clear int */
DEV_SET_BUSY( INT_DKP ) ; /* set busy */
DEV_CLR_DONE( INT_DKP ) ; /* clear done */
DEV_UPDATE_INTR ; /* update ints */
if (dkp_diagmode) { /* in diagnostic mode? */
dkp_diagmode = 0; /* reset it */
dkp_diagmode = 0; /* reset it */
if (dtype == TYPE_6097) dkp_ussc = 010001; /* (BKR - quad floppy) */
if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */
if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */
}
else { /* normal mode ... */
if (dkp_go ()) break; /* new cmd, error? */
if (dkp_go (pulse)) /* do command */
break ; /* break if no error */
}
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
dev_done = dev_done | INT_DKP; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
dkp_sta = dkp_sta | STA_DONE;
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
DEV_SET_DONE( INT_DKP ) ; /* set done */
DEV_UPDATE_INTR ; /* update ints */
dkp_sta = dkp_sta | STA_DONE; /* set controller done */
break;
case iopC: /* clear */
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
dev_done = dev_done & ~INT_DKP; /* clear done */
int_req = int_req & ~INT_DKP; /* clear int */
dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS);
if (dkp_unit[u].FUNC != FCCY_SEEK) sim_cancel (&dkp_unit[u]);
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
DEV_CLR_DONE( INT_DKP ) ; /* set done */
DEV_UPDATE_INTR ; /* update ints */
dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS); /* clear controller flags */
if (dkp_unit[u].FUNC != FCCY_SEEK)
sim_cancel (&dkp_unit[u]); /* cancel any r/w op */
break;
case iopP: /* pulse */
dev_done = dev_done & ~INT_DKP; /* clear done */
if (dkp_go ()) break; /* new seek command */
dev_done = dev_done | INT_DKP; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set seek done */
if ( dkp_diagmode )
{
dkp_diagmode = 0 ; /* clear DG diagnostic mode */
}
else
{
DEV_CLR_DONE( INT_DKP ) ; /* clear done */
DEV_UPDATE_INTR ;
/* DG "undocumented feature": 'P' pulse can not start a read/write operation!
* Diagnostic routines will use this crock to do 'crazy things' to size a disk
* and many assume that a recal is done, other assume that they can stop the
* read operation before any damage is done. Must also [re]calculate unit, function
* and type because DOx instruction may have updated the controller info after
* start of this procedure and before our 'P' handler. BKR
*/
if (dkp_go(pulse))
break; /* no error - do not set done and status */
}
DEV_SET_DONE( INT_DKP ) ; /* set done */
DEV_UPDATE_INTR ; /* update ints */
dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set controller seek done */
break;
} /* end case pulse */
} /* end case pulse */
return rval;
}
/* New command, start vs pulse handled externally
Returns true if command ok, false if error
*/
t_stat dkp_go (void)
t_stat dkp_go ( int32 pulse )
{
UNIT *uptr;
int32 newcyl, func, u, dtype;
UNIT * uptr;
int32 oldCyl, u, dtype;
dkp_sta = dkp_sta & ~STA_EFLGS; /* clear errors */
u = GET_UNIT (dkp_ussc); /* get unit number */
@@ -560,31 +667,117 @@ if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) {
dkp_sta = dkp_sta | STA_ERR; /* attached or busy? */
return FALSE;
}
dtype = GET_DTYPE (uptr->flags); /* get drive type */
func = GET_CMD (dkp_fccy, dtype); /* get function */
newcyl = GET_CYL (dkp_fccy, dtype); /* get cylinder */
switch (func) { /* decode command */
if (dkp_diagmode) { /* diagnostic mode? */
dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
DEV_SET_DONE( INT_DKP ) ; /* set done */
DEV_UPDATE_INTR ; /* update interrupts */
return ( TRUE ) ; /* do not do function */
}
case FCCY_READ: case FCCY_WRITE:
sim_activate (uptr, dkp_rwait); /* schedule */
oldCyl = uptr->CYL ; /* get old cylinder */
dtype = GET_DTYPE (uptr->flags); /* get drive type */
uptr->FUNC = GET_CMD (dkp_fccy, dtype) ; /* save command */
uptr->CYL = GET_CYL (dkp_fccy, dtype) ;
if ( DKP_TRACE(1) )
{
int32 xSect ;
int32 xSurf ;
int32 xCyl ;
int32 xCnt ;
xSect = GET_SECT(dkp_ussc, dtype) ;
xSurf = GET_SURF(dkp_ussc, dtype) ;
xCyl = GET_CYL (dkp_fccy, dtype) ;
xCnt = 16 - (GET_COUNT(dkp_ussc)) ;
fprintf( DKP_TRACE_FP,
" [%s:%c %-5s: %3d / %2d / %2d %2d %06o ] \r\n",
"DKP",
(char) (u + '0'),
((uptr->FUNC == FCCY_READ) ?
"read"
: ((uptr->FUNC == FCCY_WRITE) ?
"write"
: ((uptr->FUNC == FCCY_SEEK) ?
"seek"
: "<???>"
)
)
),
(unsigned) xCyl,
(unsigned) xSurf,
(unsigned) xSect,
(unsigned) (16 - xCnt),
(unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */
) ;
}
switch (uptr->FUNC) { /* decode command */
case FCCY_READ:
case FCCY_WRITE:
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE)))
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
}
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder */
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_CYL ;
}
else if ( GET_SURF(dkp_ussc, dtype) >= drv_tab[dtype].surf ) /* bad surface */
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /* older drives may not even do this... */
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /- newer disks give this error */
}
else if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */
{
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older drives may not even do this... */
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */
}
if ( (pulse != iopS) || (dkp_sta & STA_ERR) )
{
return ( FALSE ) ;
}
sim_activate (uptr, dkp_rwait); /* schedule read or write request */
break;
case FCCY_RECAL: /* recalibrate */
newcyl = 0;
func = FCCY_SEEK;
uptr->FUNC = FCCY_SEEK ; /* save command */
uptr->CYL = 0 ;
case FCCY_SEEK: /* seek */
sim_activate (uptr, dkp_swait * abs (newcyl - uptr->CYL));
if ( ! (uptr->flags & UNIT_ATT) ) /* not attached? */
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
}
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder? */
{
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
}
if ( (pulse != iopP) || (dkp_sta & STA_ERR) )
{
return ( FALSE ) ; /* only 'P' pulse start seeks! */
}
/* do the seek */
/* must check for "do we support seeking bits" flag before setting SEEK0'ish bits! */
dkp_sta = dkp_sta | (STA_SEEK0 >> u); /* set seeking */
uptr->CYL = newcyl; /* on cylinder */
oldCyl = abs(oldCyl - uptr->CYL) ;
if ( (dkp_swait) && (! (oldCyl)) ) /* enforce minimum wait if req */
oldCyl = 1 ;
sim_activate ( uptr, (dkp_swait * oldCyl) ) ;
break;
} /* end case command */
uptr->FUNC = func; /* save command */
return TRUE; /* no error */
return ( TRUE ) ; /* no error */
}
/* Unit service
If seek done, put on cylinder;
@@ -599,73 +792,127 @@ return TRUE; /* no error */
t_stat dkp_svc (UNIT *uptr)
{
int32 sc, sa, xcsa, bda;
int32 sx, dx, pa, u;
int32 sa, bda;
int32 dx, pa, u;
int32 dtype, err, newsect, newsurf;
uint32 awc;
t_stat rval;
static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */
rval = SCPE_OK;
rval = SCPE_OK;
dtype = GET_DTYPE (uptr->flags); /* get drive type */
if (dkp_diagmode) { /* diagnostic mode? */
dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
dev_done = dev_done | INT_DKP; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
return SCPE_OK; /* do not do function */
}
u = uptr - dkp_dev.units; /* get unit number */
if (uptr->FUNC == FCCY_SEEK) { /* seek? */
if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */
if ( ! (uptr->flags & UNIT_ATT) ) /* not attached? */
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error (changed during queue time?) */
}
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder? */
{
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
dev_done = dev_done | INT_DKP; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
u = uptr - dkp_dev.units; /* get unit number */
}
DEV_SET_DONE( INT_DKP ) ;
DEV_UPDATE_INTR ;
dkp_sta = (dkp_sta | (STA_SKDN0 >> u)) /* set seek done */
& ~(STA_SEEK0 >> u); /* clear seeking */
& ~(STA_SEEK0 >> u); /* clear seeking */
if ( DKP_TRACE(2) )
{
fprintf( DKP_TRACE_FP,
" [%s:%c seek : %4d ] \r\n",
"DKP",
(char) (u + '0'),
(unsigned) (uptr->CYL)
) ;
}
return SCPE_OK;
}
/* read or write */
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE)))
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
else if ((uptr->CYL >= drv_tab[dtype].cyl) || /* bad cylinder */
(GET_SURF (dkp_ussc, dtype) >= drv_tab[dtype].surf) || /* bad surface */
(GET_SECT (dkp_ussc, dtype) >= drv_tab[dtype].sect)) /* or bad sector? */
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS;
else if (GET_CYL (dkp_fccy, dtype) != uptr->CYL) /* address error? */
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS;
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
}
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder */
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_CYL ;
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
DEV_SET_DONE( INT_DKP ) ;
DEV_UPDATE_INTR ;
return SCPE_OK ;
}
else if ( GET_SURF(dkp_ussc, dtype) >= drv_tab[dtype].surf ) /* bad surface */
{
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /* older drives may not even do this... */
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /- newer disks give this error */
/* set sector to some bad value and wait then exit? */
}
else if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */
{
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older DG drives do not even give error(!), but we do */
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */
}
else {
sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */
sa = GET_SA (uptr->CYL, GET_SURF (dkp_ussc, dtype),
GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */
xcsa = GET_SA (uptr->CYL + 1, 0, 0, dtype); /* get next cyl addr */
if ((sa + sc) > xcsa ) { /* across cylinder? */
sc = xcsa - sa; /* limit transfer */
dkp_sta = dkp_sta | STA_XCY; /* xcyl error */
err = 0 ;
do {
if ( DKP_TRACE(3) )
{
fprintf( DKP_TRACE_FP,
" [%s:%c %-5s: %3d / %2d / %2d %06o ] \r\n",
"DKP",
(char) (u + '0'),
((uptr->FUNC == FCCY_READ) ?
"read"
: ((uptr->FUNC == FCCY_WRITE) ?
"write"
: "<???>")
),
(unsigned) (uptr->CYL),
(unsigned) (GET_SURF(dkp_ussc, dtype)),
(unsigned) (GET_SECT(dkp_ussc, dtype)),
(unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */
) ;
}
bda = sa * DKP_NUMWD * sizeof (short); /* to words, bytes */
if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */
{
/* sector overflows to 0 ;
* surface gets incremented
*/
newsurf = GET_SURF(dkp_ussc, dtype) + 1 ;
newsurf = newsurf & ((drv_tab[dtype].newf) ? USSC_M_NSURFACE : USSC_M_OSURFACE) ;
DKP_UPDATE_USSC( type, 0, newsurf, 0 )
if ( (GET_SURF(dkp_ussc, dtype)) >= drv_tab[dtype].surf )
{
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older drives may not even do this... */
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */
/* DG retains overflowed surface number,
* other vendors have different/expanded options
*/
break ;
}
}
sa = GET_SA (uptr->CYL, GET_SURF (dkp_ussc, dtype),
GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */
bda = sa * DKP_NUMWD * sizeof(uint16) ; /* to words, bytes */
err = fseek (uptr->fileref, bda, SEEK_SET); /* position drive */
if (uptr->FUNC == FCCY_READ) { /* read? */
for (sx = 0; sx < sc; sx++) { /* loop thru sectors */
awc = fxread (tbuf, sizeof(uint16), DKP_NUMWD, uptr->fileref);
for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0;
if (err = ferror (uptr->fileref)) break;
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */
pa = MapAddr (dkp_map, (dkp_ma & AMASK));
if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx];
dkp_ma = (dkp_ma + 1) & AMASK;
}
}
}
if (uptr->FUNC == FCCY_WRITE) { /* write? */
for (sx = 0; sx < sc; sx++) { /* loop thru sectors */
else if (uptr->FUNC == FCCY_WRITE) { /* write? */
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */
pa = MapAddr (dkp_map, (dkp_ma & AMASK));
tbuf[dx] = M[pa];
@@ -674,27 +921,41 @@ else {
fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref);
if (err = ferror (uptr->fileref)) break;
}
}
if (err != 0) {
perror ("DKP I/O error");
clearerr (uptr->fileref);
clearerr (uptr->fileref);
rval = SCPE_IOERR;
break ;
}
sa = sa + sc; /* update sector addr */
newsect = sa % drv_tab[dtype].sect;
newsurf = (sa / drv_tab[dtype].sect) % drv_tab[dtype].surf;
dkp_ussc = (dkp_ussc & USSC_UNIT) | ((dkp_ussc + sc) & USSC_M_COUNT) |
((drv_tab[dtype].newf)?
((newsurf << USSC_V_NSURFACE) | (newsect << USSC_V_NSECTOR)):
((newsurf << USSC_V_OSURFACE) | (newsect << USSC_V_OSECTOR)) );
newsect = GET_SECT (dkp_ussc, dtype) + 1 ; /* update next sector */
newsurf = GET_SURF (dkp_ussc, dtype) ; /* and next head */
/* (count set below) */
DKP_UPDATE_USSC( type, 1, newsurf, newsect )
} /* end read/write loop */
while ( (GET_COUNT(dkp_ussc)) ) ;
dkp_sta = dkp_sta | STA_DONE; /* set status */
if ( DKP_TRACE(4) )
{
fprintf( DKP_TRACE_FP,
" [%s:%c %-5s: %3d / %2d / %2d %06o ] \r\n",
"DKP",
(char) (u + '0'),
"post",
(unsigned) (uptr->CYL),
(unsigned) (GET_SURF(dkp_ussc, dtype)),
(unsigned) (GET_SECT(dkp_ussc, dtype)),
(unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */
) ;
}
}
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
dev_done = dev_done | INT_DKP; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
DEV_CLR_BUSY( INT_DKP ) ;
DEV_SET_DONE( INT_DKP ) ;
DEV_UPDATE_INTR ;
return rval;
}
@@ -705,9 +966,9 @@ t_stat dkp_reset (DEVICE *dptr)
int32 u;
UNIT *uptr;
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
dev_done = dev_done & ~INT_DKP; /* clear done, int */
int_req = int_req & ~INT_DKP;
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
DEV_CLR_DONE( INT_DKP ) ; /* clear done */
DEV_UPDATE_INTR ; /* update ints */
dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */
dkp_diagmode = 0; /* clear diagnostic mode */
dkp_map = 0;
@@ -724,7 +985,7 @@ return SCPE_OK;
t_stat dkp_attach (UNIT *uptr, char *cptr)
{
int32 i, p;
t_stat r;
t_stat r;
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; /* restore capac */
r = attach_unit (uptr, cptr); /* attach */
@@ -751,10 +1012,12 @@ return SCPE_OK;
/* Bootstrap routine */
#if defined(_OLD_CODE_)
#define BOOT_START 02000
#define BOOT_UNIT 02021
#define BOOT_SEEK 02022
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
#define BOOT_LEN (sizeof(boot_rom) / sizeof(int32))
static const int32 boot_rom[] = {
0060233, /* NIOC 0,DKP ; clear disk */
@@ -774,12 +1037,13 @@ static const int32 boot_rom[] = {
0101113, /* MOVL# 0,0,SNC ; skip if done */
0000776, /* JMP .-2 */
0000377, /* JMP 377 */
0000016, /* USSC: 0.B1+0.B7+0.B11+16 */
0000016, /* USSC: 0.B1+0.B7+0.B11+16 */
0175000, /* SEKCMD: 175000 */
0074000, /* SEKDN: 074000 */
0074000, /* SEKDN: 074000 */
0174000 /* REDCMD: 174000 */
};
t_stat dkp_boot (int32 unitno, DEVICE *dptr)
{
int32 i, dtype;
@@ -794,3 +1058,27 @@ saved_PC = BOOT_START;
SR = 0100000 + DEV_DKP;
return SCPE_OK;
}
#endif /* _OLD_CODE_ */
#define BOOT_START 0375
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
static const int32 boot_rom[] = {
0062677 /* IORST ; reset the I/O system */
, 0060133 /* NIOS DKP ; start the disk */
, 0000377 /* JMP 377 ; wait for the world */
} ;
t_stat dkp_boot (int32 unitno, DEVICE *dptr)
{
int32 i;
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = (uint16) boot_rom[i];
saved_PC = BOOT_START;
SR = 0100000 + DEV_DKP;
return SCPE_OK;
}