179 lines
7.9 KiB
C
179 lines
7.9 KiB
C
/*************************************************************************
|
|
* *
|
|
* Copyright (c) 2022 Howard M. Harte. *
|
|
* https://github.com/hharte *
|
|
* *
|
|
* 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 NON- *
|
|
* INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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 names of The Authors shall *
|
|
* not be used in advertising or otherwise to promote the sale, use or *
|
|
* other dealings in this Software without prior written authorization *
|
|
* from the Authors. *
|
|
* *
|
|
* Based on s100_64fdc.c *
|
|
* *
|
|
* Module Description: *
|
|
* Tarbell Double-Density Floppy Controller module for SIMH. *
|
|
* This module is a wrapper around the wd179x FDC module. *
|
|
* *
|
|
* Reference: *
|
|
* http://www.bitsavers.org/pdf/tarbell/Tarbell_Double_Density_Floppy_Disk_Interface_Jul81.pdf
|
|
* *
|
|
*************************************************************************/
|
|
|
|
#include "altairz80_defs.h"
|
|
#include "wd179x.h"
|
|
|
|
#define DEV_NAME "TDD"
|
|
|
|
/* Debug flags */
|
|
#define STATUS_MSG (1 << 0)
|
|
#define DRIVE_MSG (1 << 1)
|
|
#define VERBOSE_MSG (1 << 2)
|
|
#define IRQ_MSG (1 << 3)
|
|
|
|
#define TDD_MAX_DRIVES 4
|
|
|
|
#define TDD_IO_BASE 0x7C
|
|
#define TDD_IO_SIZE 0x2
|
|
#define TDD_IO_MASK (TDD_IO_SIZE - 1)
|
|
|
|
typedef struct {
|
|
PNP_INFO pnp; /* Plug and Play */
|
|
} TDD_INFO;
|
|
|
|
extern WD179X_INFO_PUB *wd179x_infop;
|
|
|
|
static TDD_INFO tdd_info_data = { { 0x0000, 0, TDD_IO_BASE, TDD_IO_SIZE } };
|
|
|
|
extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
|
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
|
int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap);
|
|
|
|
extern uint32 PCX; /* external view of PC */
|
|
|
|
#define TDD_CAPACITY (77*1*26*128) /* Default SSSD 8" (IBM 3740) Disk Capacity */
|
|
|
|
static t_stat tdd_reset(DEVICE *tdd_dev);
|
|
|
|
static int32 tdd_control(const int32 port, const int32 io, const int32 data);
|
|
static const char* tdd_description(DEVICE *dptr);
|
|
|
|
#define TDD_FLAG_EOJ (1 << 7) /* End of Job (INTRQ) */
|
|
|
|
static UNIT tdd_unit[] = {
|
|
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) },
|
|
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) },
|
|
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) },
|
|
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) }
|
|
};
|
|
|
|
static REG tdd_reg[] = {
|
|
{ NULL }
|
|
};
|
|
|
|
#define TDD_NAME "Tarbell Double-Density FDC"
|
|
|
|
static const char* tdd_description(DEVICE *dptr) {
|
|
if (dptr == NULL) {
|
|
return NULL;
|
|
}
|
|
return TDD_NAME;
|
|
}
|
|
|
|
static MTAB tdd_mod[] = {
|
|
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
|
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
|
{ 0 }
|
|
};
|
|
|
|
/* Debug Flags */
|
|
static DEBTAB tdd_dt[] = {
|
|
{ "STATUS", STATUS_MSG, "Status messages" },
|
|
{ "DRIVE", DRIVE_MSG, "Drive messages" },
|
|
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
|
{ "IRQ", IRQ_MSG, "IRQ messages" },
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
DEVICE tdd_dev = {
|
|
DEV_NAME, tdd_unit, tdd_reg, tdd_mod,
|
|
TDD_MAX_DRIVES, 10, 31, 1, TDD_MAX_DRIVES, TDD_MAX_DRIVES,
|
|
NULL, NULL, &tdd_reset,
|
|
NULL, &wd179x_attach, &wd179x_detach,
|
|
&tdd_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
|
|
tdd_dt, NULL, NULL, NULL, NULL, NULL, &tdd_description
|
|
};
|
|
|
|
/* Reset routine */
|
|
static t_stat tdd_reset(DEVICE *dptr)
|
|
{
|
|
PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt;
|
|
|
|
if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */
|
|
/* Unmap I/O Ports */
|
|
sim_map_resource(pnp->io_base, 1, RESOURCE_TYPE_IO, &tdd_control, "tdd_control", TRUE);
|
|
} else {
|
|
/* Connect TDD Disk Flags and Control Register */
|
|
if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &tdd_control, "tdd_control", FALSE) != 0) {
|
|
sim_printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base);
|
|
return SCPE_ARG;
|
|
}
|
|
}
|
|
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Tarbell pp. 12-5 Disk Control/Status */
|
|
static int32 tdd_control(const int32 port, const int32 io, const int32 data)
|
|
{
|
|
int32 result = 0;
|
|
if(io) { /* I/O Write */
|
|
if ((port & TDD_IO_MASK) == 0) {
|
|
wd179x_infop->fdc_head = (data & 0x40) >> 6;
|
|
wd179x_infop->sel_drive = (data & 0x30) >> 4;
|
|
wd179x_infop->ddens = (data & 0x08) >> 3;
|
|
|
|
sim_debug(DRIVE_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT " WR CTRL(0x%02x) = 0x%02x: Drive: %d, Head: %d, %s-Density.\n",
|
|
PCX, port,
|
|
data & 0xFF,
|
|
wd179x_infop->sel_drive,
|
|
wd179x_infop->fdc_head,
|
|
wd179x_infop->ddens == 1 ? "Double" : "Single");
|
|
} else {
|
|
sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT
|
|
" Write Extended Address, Port 0x%02x=0x%02x\n", PCX, port, data);
|
|
}
|
|
} else { /* I/O Read */
|
|
if ((port & TDD_IO_MASK) == 0) {
|
|
result = (wd179x_infop->intrq) ? 0 : TDD_FLAG_EOJ;
|
|
sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT
|
|
" Read EOJ, Port 0x%02x Result 0x%02x\n", PCX, port, result);
|
|
} else {
|
|
result = (wd179x_infop->drq) ? TDD_FLAG_EOJ : 0;
|
|
sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT
|
|
" Read DRQ, Port 0x%02x Result 0x%02x\n", PCX, port, result);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|