724 lines
25 KiB
C
724 lines
25 KiB
C
/* isbc206.c: Intel iSBC 206 disk adapter
|
|
|
|
Copyright (c) 2017, William A. Beech
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of William A. Beech shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from William A. Beech.
|
|
|
|
MODIFICATIONS:
|
|
|
|
31 Oct 17 - Original file.
|
|
|
|
NOTES:
|
|
|
|
This controller will mount 1 removable Hard Disk (IBM 2315)and three Hard Disk fixed disk
|
|
images on drives :F0: thru :F3: addressed at ports 068H to 06FH.
|
|
|
|
Registers:
|
|
|
|
068H - Read - Subsystem status
|
|
bit 0 - ready status of drive 0
|
|
bit 1 - ready status of drive 1
|
|
bit 2 - state of channel's interrupt FF
|
|
bit 3 - controller presence indicator
|
|
bit 4 - DD controller presence indicator
|
|
bit 5 - ready status of drive 2
|
|
bit 6 - ready status of drive 3
|
|
bit 7 - zero
|
|
|
|
069H - Read - Read result type (bits 2-7 are zero)
|
|
00 - I/O complete with error
|
|
01 - Reserved
|
|
10 - Result byte contains diskette ready status
|
|
11 - Reserved
|
|
069H - Write - IOPB address low byte.
|
|
|
|
06AH - Write - IOPB address high byte and start operation.
|
|
|
|
06BH - Read - Read result byte
|
|
If result type is 00H
|
|
0x01 - ID field miscompare
|
|
0x02 - Data field CRC error
|
|
0x04 - Seek error
|
|
0x08 - Bad sector address error
|
|
0x0A - ID field CRC error
|
|
0x0B - Protocol violations
|
|
0x0C - Bad track address error
|
|
0x0E - No ID address mark or sector found
|
|
0x0F - D=Bad data field address mark
|
|
0x10 - Format error
|
|
0x20 - write protect
|
|
0x40 - write error
|
|
0x80 - not ready
|
|
|
|
06FH - Write - Reset diskette system.
|
|
|
|
Operations:
|
|
NOP - 0x00
|
|
Seek - 0x01
|
|
Format Track - 0x02
|
|
Recalibrate - 0x03
|
|
Read Data - 0x04
|
|
Verify CRC - 0x05
|
|
Write Data - 0x06
|
|
Write Deleted Data - 0x07
|
|
|
|
IOPB - I/O Parameter Block
|
|
Byte 0 - Channel Word
|
|
bit 3 - data word length (=8-bit, 1=16-bit)
|
|
bit 4-5 - interrupt control
|
|
00 - I/O complete interrupt to be issued
|
|
01 - I/O complete interrupts are disabled
|
|
10 - illegal code
|
|
11 - illegal code
|
|
bit 6- randon format sequence
|
|
|
|
Byte 1 - Diskette Instruction
|
|
bit 0-2 - operation code
|
|
000 - no operation
|
|
001 - seek
|
|
010 - format track
|
|
011 - recalibrate
|
|
100 - read data
|
|
101 - verify CRC
|
|
110 - write data
|
|
111 - write deleted data
|
|
bit 3 - data word length ( same as byte-0, bit-3)
|
|
bit 4-5 - unit select
|
|
00 - drive 0
|
|
01 - drive 1
|
|
10 - drive 2
|
|
11 - drive 3
|
|
bit 6-7 - reserved (zero)
|
|
|
|
Byte 2 - Number of Records
|
|
|
|
Byte 4 - Track Address
|
|
|
|
Byte 5 - Sector Address
|
|
|
|
Byte 6 - Buffer Low Address
|
|
|
|
Byte 7 - Buffer High Address
|
|
|
|
u3 -
|
|
u4 -
|
|
u5 -
|
|
u6 - hdd number.
|
|
|
|
*/
|
|
|
|
#include "system_defs.h" /* system header in system dir */
|
|
|
|
//#if defined (SBC206_NUM) && (SBC206_NUM > 0)
|
|
|
|
#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */
|
|
#define UNIT_WPMODE (1 << UNIT_V_WPMODE)
|
|
|
|
#define HDD_NUM 2 //one fixed and one removable
|
|
|
|
//disk controller operations
|
|
#define DNOP 0x00 //HDC no operation
|
|
#define DSEEK 0x01 //HDC seek
|
|
#define DFMT 0x02 //HDC format
|
|
#define DHOME 0x03 //HDC home
|
|
#define DREAD 0x04 //HDC read
|
|
#define DVCRC 0x05 //HDC verify CRC
|
|
#define DWRITE 0x06 //HDC write
|
|
|
|
//status
|
|
#define RDY0 0x01 //HDD 0 ready
|
|
#define RDY1 0x02 //HDD 1 ready
|
|
#define HDCINT 0x04 //HDC interrupt flag
|
|
#define HDCPRE 0x08 //HDC board present
|
|
|
|
//result type
|
|
#define ROK 0x00 //HDC returned error
|
|
//#define RCHG 0x02 //HDC returned ok
|
|
#define RCHG 0x01 //HDC returned ok
|
|
|
|
// If result type is RERR then rbyte is
|
|
#define RB0DR 0x01 //deleted record
|
|
#define RB0CRC 0x02 //CRC error
|
|
#define RB0SEK 0x04 //seek error
|
|
#define RB0ADR 0x08 //address error
|
|
#define RB0OU 0x10 //data overrun/underrun
|
|
#define RB0WP 0x20 //write protect
|
|
#define RB0WE 0x40 //write error
|
|
#define RB0NR 0x80 //not ready
|
|
|
|
// If result type is ROK then rbyte is
|
|
#define RB1RD0 0x40 //drive 0 ready
|
|
#define RB1RD1 0x80 //drive 1 ready
|
|
|
|
//disk geometry values
|
|
#define MDSHD 3796992 //hard disk size MB
|
|
#define MAXSECHD 144 //hard disk last sector (2 heads/2 tracks)
|
|
#define MAXTRKHD 206 //hard disk last track
|
|
|
|
#define isbc206_NAME "Intel iSBC 206 Hard Disk Controller Board"
|
|
|
|
/* external globals */
|
|
|
|
extern uint16 PCX;
|
|
|
|
/* external function prototypes */
|
|
|
|
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16, uint16, uint8);
|
|
extern uint8 unreg_dev(uint16 port);
|
|
extern uint8 get_mbyte(uint16 addr);
|
|
extern void put_mbyte(uint16 addr, uint8 val);
|
|
|
|
/* function prototypes */
|
|
|
|
t_stat isbc206_cfg(uint16 base, uint16 size, uint8 devnum);
|
|
t_stat isbc206_clr(void);
|
|
t_stat isbc206_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
t_stat isbc206_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
t_stat isbc206_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
t_stat isbc206_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
|
t_stat isbc206_reset(DEVICE *dptr);
|
|
void isbc206_reset_dev(void);
|
|
t_stat isbc206_attach (UNIT *uptr, CONST char *cptr);
|
|
t_stat isbc206_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
uint8 isbc206r0(t_bool io, uint8 data, uint8 devnum); /* isbc206 port 0 */
|
|
uint8 isbc206r1(t_bool io, uint8 data, uint8 devnum); /* isbc206 port 1 */
|
|
uint8 isbc206r2(t_bool io, uint8 data, uint8 devnum); /* isbc206 port 2 */
|
|
uint8 isbc206r3(t_bool io, uint8 data, uint8 devnum); /* isbc206 port 3 */
|
|
uint8 isbc206r7(t_bool io, uint8 data, uint8 devnum); /* isbc206 port 7 */
|
|
void isbc206_diskio(void); //do actual disk i/o
|
|
|
|
/* globals */
|
|
|
|
int isbc206_onetime = 1;
|
|
static const char* isbc206_desc(DEVICE *dptr) {
|
|
return isbc206_NAME;
|
|
}
|
|
|
|
typedef struct { //HDD definition
|
|
int t0;
|
|
int rdy;
|
|
uint8 sec;
|
|
uint8 cyl;
|
|
} HDDDEF;
|
|
|
|
typedef struct { //HDC definition
|
|
uint8 baseport; //HDC base port
|
|
uint8 intnum; //interrupt number
|
|
uint8 verb; //verbose flag
|
|
uint16 iopb; //HDC IOPB
|
|
uint8 stat; //HDC status
|
|
uint8 rdychg; //HDC ready change
|
|
uint8 rtype; //HDC result type
|
|
uint8 rbyte0; //HDC result byte for type 00
|
|
uint8 rbyte1; //HDC result byte for type 10
|
|
uint8 intff; //HDC interrupt FF
|
|
HDDDEF hd[HDD_NUM]; //indexed by the HDD number
|
|
} HDCDEF;
|
|
|
|
HDCDEF hdc206; //indexed by the isbc-206 instance number
|
|
|
|
|
|
UNIT isbc206_unit[] = { // 2 HDDs
|
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSHD) },
|
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSHD) },
|
|
{ NULL }
|
|
};
|
|
|
|
REG isbc206_reg[] = {
|
|
{ HRDATA (STAT0, hdc206.stat, 8) }, /* isbc206 0 status */
|
|
{ HRDATA (RTYP0, hdc206.rtype, 8) }, /* isbc206 0 result type */
|
|
{ HRDATA (RBYT0A, hdc206.rbyte0, 8) }, /* isbc206 0 result byte 0 */
|
|
{ HRDATA (RBYT0B, hdc206.rbyte1, 8) }, /* isbc206 0 result byte 1 */
|
|
{ HRDATA (INTFF0, hdc206.intff, 8) }, /* isbc206 0 interrupt f/f */
|
|
{ NULL }
|
|
};
|
|
|
|
MTAB isbc206_mod[] = {
|
|
{ UNIT_WPMODE, 0, "RW", "RW", &isbc206_set_mode },
|
|
{ UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc206_set_mode },
|
|
{ MTAB_XTD | MTAB_VDV, 0, NULL, "VERB", &isbc206_set_verb,
|
|
NULL, NULL, "Sets the verbose mode for iSBC206"},
|
|
{ MTAB_XTD | MTAB_VDV, 0, NULL, "PORT", &isbc206_set_port,
|
|
NULL, NULL, "Sets the base port for iSBC206"},
|
|
{ MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc206_set_int,
|
|
NULL, NULL, "Sets the interrupt number for iSBC206"},
|
|
{ MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc206_show_param, NULL,
|
|
"show configured parameters for iSBC206" },
|
|
{ 0 }
|
|
};
|
|
|
|
DEBTAB isbc206_debug[] = {
|
|
{ "ALL", DEBUG_all },
|
|
{ "FLOW", DEBUG_flow },
|
|
{ "READ", DEBUG_read },
|
|
{ "WRITE", DEBUG_write },
|
|
{ "XACK", DEBUG_xack },
|
|
{ NULL }
|
|
};
|
|
|
|
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
|
|
|
DEVICE isbc206_dev = {
|
|
"SBC206", //name
|
|
isbc206_unit, //units
|
|
isbc206_reg, //registers
|
|
isbc206_mod, //modifiers
|
|
HDD_NUM, //numunits
|
|
16, //aradix
|
|
16, //awidth
|
|
1, //aincr
|
|
16, //dradix
|
|
8, //dwidth
|
|
NULL, //examine
|
|
NULL, //deposit
|
|
isbc206_reset, //reset
|
|
NULL, //boot
|
|
&isbc206_attach, //attach
|
|
NULL, //detach
|
|
NULL, //ctxt
|
|
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
|
|
0, //dctrl
|
|
isbc206_debug, //debflags
|
|
NULL, //msize
|
|
NULL, //lname
|
|
NULL, //help routine
|
|
NULL, //attach help routine
|
|
NULL, //help context
|
|
&isbc206_desc //device description
|
|
};
|
|
|
|
// iSBC 201 configuration
|
|
|
|
t_stat isbc206_cfg(uint16 baseport, uint16 devnum, uint8 intnum)
|
|
{
|
|
int i;
|
|
UNIT *uptr;
|
|
|
|
// one-time initialization for all FDDs for this FDC instance
|
|
for (i = 0; i < HDD_NUM; i++) {
|
|
uptr = isbc206_dev.units + i;
|
|
uptr->u6 = i; //fdd unit number
|
|
}
|
|
hdc206.baseport = baseport & BYTEMASK; //set port
|
|
hdc206.intnum = intnum; //set interrupt
|
|
hdc206.verb = 0; //clear verb
|
|
reg_dev(isbc206r0, hdc206.baseport, 0, 0); //read status
|
|
reg_dev(isbc206r1, hdc206.baseport + 1, 0, 0); //read rslt type/write IOPB addr-l
|
|
reg_dev(isbc206r2, hdc206.baseport + 2, 0, 0); //write IOPB addr-h and start
|
|
reg_dev(isbc206r3, hdc206.baseport + 3, 0, 0); //read rstl byte
|
|
reg_dev(isbc206r7, hdc206.baseport + 7, 0, 0); //write reset fdc201
|
|
isbc206_reset_dev(); //software reset
|
|
// if (hdc206.verb)
|
|
sim_printf(" sbc206: Enabled base port at 0%02XH, Interrupt #=%02X, %s\n",
|
|
hdc206.baseport, hdc206.intnum, hdc206.verb ? "Verbose" : "Quiet" );
|
|
return SCPE_OK;
|
|
}
|
|
|
|
// iSBC 201 deconfiguration
|
|
|
|
t_stat isbc206_clr(void)
|
|
{
|
|
hdc206.intnum = -1; //set default interrupt
|
|
hdc206.verb = 0; //set verb = 0
|
|
unreg_dev(hdc206.baseport); //read status
|
|
unreg_dev(hdc206.baseport + 1); //read rslt type/write IOPB addr-l
|
|
unreg_dev(hdc206.baseport + 2); //write IOPB addr-h and start
|
|
unreg_dev(hdc206.baseport + 3); //read rstl byte
|
|
unreg_dev(hdc206.baseport + 7); //write reset fdc201
|
|
// if (hdc206.verb)
|
|
sim_printf(" sbc206: Disabled\n");
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* isbc206 set mode = Write protect */
|
|
|
|
t_stat isbc206_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
if (uptr == NULL)
|
|
return SCPE_ARG;
|
|
if (uptr->flags & UNIT_ATT)
|
|
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
|
|
if (val & UNIT_WPMODE) { /* write protect */
|
|
uptr->flags |= val;
|
|
if (hdc206.verb)
|
|
sim_printf(" sbc206: WP\n");
|
|
} else { /* read write */
|
|
uptr->flags &= ~val;
|
|
if (hdc206.verb)
|
|
sim_printf(" sbc206: RW\n");
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
// set base address parameter
|
|
|
|
t_stat isbc206_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
uint32 size, result;
|
|
|
|
if (uptr == NULL)
|
|
return SCPE_ARG;
|
|
result = sscanf(cptr, "%02x", &size);
|
|
hdc206.baseport = size;
|
|
// if (hdc206.verb)
|
|
sim_printf("SBC206: Base port=%04X\n", hdc206.baseport);
|
|
reg_dev(isbc206r0, hdc206.baseport, 0, 0); //read status
|
|
reg_dev(isbc206r1, hdc206.baseport + 1, 0, 0); //read rslt type/write IOPB addr-l
|
|
reg_dev(isbc206r2, hdc206.baseport + 2, 0, 0); //write IOPB addr-h and start
|
|
reg_dev(isbc206r3, hdc206.baseport + 3, 0, 0); //read rstl byte
|
|
reg_dev(isbc206r7, hdc206.baseport + 7, 0, 0); //write reset fdc202
|
|
return SCPE_OK;
|
|
}
|
|
|
|
// set interrupt parameter
|
|
|
|
t_stat isbc206_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
uint32 size, result;
|
|
|
|
if (uptr == NULL)
|
|
return SCPE_ARG;
|
|
result = sscanf(cptr, "%02x", &size);
|
|
hdc206.intnum = size;
|
|
// if (hdc206.verb)
|
|
sim_printf("SBC206: Interrupt number=%04X\n", hdc206.intnum);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat isbc206_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
if (uptr == NULL)
|
|
return SCPE_ARG;
|
|
if (cptr == NULL)
|
|
return SCPE_ARG;
|
|
if (strncasecmp(cptr, "OFF", 4) == 0) {
|
|
hdc206.verb = 0;
|
|
return SCPE_OK;
|
|
}
|
|
if (strncasecmp(cptr, "ON", 3) == 0) {
|
|
hdc206.verb = 1;
|
|
sim_printf(" SBC206: hdc206.verb=%d\n", hdc206.verb);
|
|
return SCPE_OK;
|
|
}
|
|
return SCPE_ARG;
|
|
}
|
|
|
|
// show configuration parameters
|
|
|
|
t_stat isbc206_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
|
{
|
|
if (uptr == NULL)
|
|
return SCPE_ARG;
|
|
fprintf(st, "%s Base port at %04X Interrupt # is %i %s",
|
|
((isbc206_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled",
|
|
hdc206.baseport, hdc206.intnum,
|
|
hdc206.verb ? "Verbose" : "Quiet"
|
|
);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Hardware reset routine */
|
|
|
|
t_stat isbc206_reset(DEVICE *dptr)
|
|
{
|
|
if (dptr == NULL)
|
|
return SCPE_ARG;
|
|
isbc206_reset_dev(); //software reset
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Software reset routine */
|
|
|
|
void isbc206_reset_dev(void)
|
|
{
|
|
int32 i;
|
|
UNIT *uptr;
|
|
|
|
hdc206.stat = 0; //clear status
|
|
for (i = 0; i < HDD_NUM; i++) { /* handle all units */
|
|
uptr = isbc206_dev.units + i;
|
|
hdc206.stat |= (HDCPRE + 0x80); //set the HDC status
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
if (uptr->flags & UNIT_ATT) { /* if attached */
|
|
switch(i){
|
|
case 0:
|
|
hdc206.stat |= RDY0; //set HDD 0 ready
|
|
hdc206.rbyte1 |= RB1RD0;
|
|
break;
|
|
case 1:
|
|
hdc206.stat |= RDY1; //set HDD 1 ready
|
|
hdc206.rbyte1 |= RB1RD1;
|
|
break;
|
|
}
|
|
hdc206.rdychg = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* isbc206 attach - attach an .IMG file to a HDD */
|
|
|
|
t_stat isbc206_attach (UNIT *uptr, CONST char *cptr)
|
|
{
|
|
t_stat r;
|
|
uint8 hddnum;
|
|
|
|
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
|
sim_printf(" isbc206_attach: Attach error %d\n", r);
|
|
return r;
|
|
}
|
|
hddnum = uptr->u6;
|
|
switch(hddnum){
|
|
case 0:
|
|
hdc206.stat |= RDY0; //set HDD 0 ready
|
|
hdc206.rbyte1 |= RB1RD0;
|
|
break;
|
|
case 1:
|
|
hdc206.stat |= RDY1; //set HDD 1 ready
|
|
hdc206.rbyte1 |= RB1RD1;
|
|
break;
|
|
}
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* iSBC206 control port functions */
|
|
|
|
uint8 isbc206r0(t_bool io, uint8 data, uint8 devnum)
|
|
{
|
|
if (io == 0) { /* read status*/
|
|
return hdc206.stat;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint8 isbc206r1(t_bool io, uint8 data, uint8 devnum)
|
|
{
|
|
if (io == 0) { /* read data port */
|
|
hdc206.intff = 0; //clear interrupt FF
|
|
hdc206.stat &= ~(HDCINT + 0x80);
|
|
hdc206.rtype = ROK;
|
|
return hdc206.rtype;
|
|
} else { /* write data port */
|
|
hdc206.iopb = data;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint8 isbc206r2(t_bool io, uint8 data, uint8 devnum)
|
|
{
|
|
if (io == 0) { /* read data port */
|
|
;
|
|
} else { /* write data port */
|
|
hdc206.iopb |= (data << 8);
|
|
isbc206_diskio();
|
|
if (hdc206.intff)
|
|
hdc206.stat |= HDCINT;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint8 isbc206r3(t_bool io, uint8 data, uint8 devnum)
|
|
{
|
|
if (io == 0) { /* read data port */
|
|
if (hdc206.rtype == ROK) {
|
|
return hdc206.rbyte0;
|
|
} else {
|
|
if (hdc206.rdychg) {
|
|
return hdc206.rbyte1;
|
|
} else {
|
|
return hdc206.rbyte0;
|
|
}
|
|
}
|
|
} else { /* write data port */
|
|
; //stop diskette operation
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
uint8 isbc206r7(t_bool io, uint8 data, uint8 devnum)
|
|
{
|
|
if (io == 0) { /* read data port */
|
|
;
|
|
} else { /* write data port */
|
|
isbc206_reset_dev();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// perform the actual disk I/O operation
|
|
|
|
void isbc206_diskio(void)
|
|
{
|
|
uint8 cw, di, nr, ta, sa, data, nrptr;
|
|
uint16 ba;
|
|
uint32 dskoff;
|
|
uint8 hddnum, fmtb;
|
|
uint32 i;
|
|
UNIT *uptr;
|
|
uint8 *fbuf;
|
|
|
|
//parse the IOPB
|
|
cw = get_mbyte(hdc206.iopb);
|
|
di = get_mbyte(hdc206.iopb + 1);
|
|
nr = get_mbyte(hdc206.iopb + 2);
|
|
ta = get_mbyte(hdc206.iopb + 3);
|
|
sa = get_mbyte(hdc206.iopb + 4);
|
|
ba = get_mbyte(hdc206.iopb + 5);
|
|
hddnum = (di & 0x30) >> 4;
|
|
uptr = isbc206_dev.units + hddnum;
|
|
fbuf = (uint8 *) (isbc206_dev.units + hddnum)->filebuf;
|
|
//check for not ready
|
|
switch(hddnum) {
|
|
case 0:
|
|
if ((hdc206.stat & RDY0) == 0) {
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = RB0NR;
|
|
hdc206.intff = 1; //set interrupt FF
|
|
sim_printf("\n SBC206: HDD %d - Ready error", hddnum);
|
|
return;
|
|
}
|
|
break;
|
|
case 1:
|
|
if ((hdc206.stat & RDY1) == 0) {
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = RB0NR;
|
|
hdc206.intff = 1; //set interrupt FF
|
|
sim_printf("\n SBC206: HDD %d - Ready error", hddnum);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
//check for address error
|
|
if (
|
|
((di & 0x07) != DHOME) && (
|
|
(sa > MAXSECHD) ||
|
|
((sa + nr) > (MAXSECHD + 1)) ||
|
|
(sa == 0) ||
|
|
(ta > MAXTRKHD)
|
|
)) {
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = RB0ADR;
|
|
hdc206.intff = 1; //set interrupt FF
|
|
sim_printf("\n SBC206: HDD %d - Address error sa=%02X nr=%02X ta=%02X PCX=%04X",
|
|
hddnum, sa, nr, ta, PCX);
|
|
return;
|
|
}
|
|
switch (di & 0x07) {
|
|
case DNOP:
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
hdc206.intff = 1; //set interrupt FF
|
|
break;
|
|
case DSEEK:
|
|
hdc206.hd[hddnum].sec = sa;
|
|
hdc206.hd[hddnum].cyl = ta;
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
hdc206.intff = 1; //set interrupt FF
|
|
break;
|
|
case DHOME:
|
|
hdc206.hd[hddnum].sec = sa;
|
|
hdc206.hd[hddnum].cyl = 0;
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
hdc206.intff = 1; //set interrupt FF
|
|
break;
|
|
case DVCRC:
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
hdc206.intff = 1; //set interrupt FF
|
|
break;
|
|
case DFMT:
|
|
//check for WP
|
|
if(uptr->flags & UNIT_WPMODE) {
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = RB0WP;
|
|
hdc206.intff = 1; //set interrupt FF
|
|
sim_printf("\n SBC206: HDD %d - Write protect error DFMT", hddnum);
|
|
return;
|
|
}
|
|
fmtb = get_mbyte(ba); //get the format byte
|
|
//calculate offset into disk image
|
|
dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128;
|
|
for(i=0; i<=((uint32)(MAXSECHD) * 128); i++) {
|
|
*(fbuf + (dskoff + i)) = fmtb;
|
|
}
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
hdc206.intff = 1; //set interrupt FF
|
|
break;
|
|
case DREAD:
|
|
nrptr = 0;
|
|
while(nrptr < nr) {
|
|
//calculate offset into disk image
|
|
dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128;
|
|
//copy sector from image to RAM
|
|
for (i=0; i<128; i++) {
|
|
data = *(fbuf + (dskoff + i));
|
|
put_mbyte(ba + i, data);
|
|
}
|
|
sa++;
|
|
ba+=0x80;
|
|
nrptr++;
|
|
}
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
hdc206.intff = 1; //set interrupt FF
|
|
break;
|
|
case DWRITE:
|
|
//check for WP
|
|
if(uptr->flags & UNIT_WPMODE) {
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = RB0WP;
|
|
hdc206.intff = 1; //set interrupt FF
|
|
sim_printf("\n SBC206: HDD %d - Write protect error DWRITE", hddnum);
|
|
return;
|
|
}
|
|
nrptr = 0;
|
|
while(nrptr < nr) {
|
|
//calculate offset into disk image
|
|
dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128;
|
|
//copy sector from image to RAM
|
|
for (i=0; i<128; i++) {
|
|
data = get_mbyte(ba + i);
|
|
*(fbuf + (dskoff + i)) = data;
|
|
}
|
|
sa++;
|
|
ba+=0x80;
|
|
nrptr++;
|
|
}
|
|
hdc206.rtype = ROK;
|
|
hdc206.rbyte0 = 0; //set no error
|
|
hdc206.intff = 1; //set interrupt FF
|
|
break;
|
|
default:
|
|
sim_printf("\n SBC206: HDD %d - isbc206_diskio bad di=%02X", hddnum, di & 0x07);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//#endif /* SBC206_NUM > 0 */
|
|
|
|
/* end of isbc206.c */
|