Changeset c5b6c90 in buchla-emu for emu/fdd.c


Ignore:
Timestamp:
07/31/2017 05:01:38 PM (7 years ago)
Author:
Thomas Lopatic <thomas@…>
Branches:
master
Children:
1489228
Parents:
1efc42c
git-author:
Thomas Lopatic <thomas@…> (07/31/2017 05:01:32 PM)
git-committer:
Thomas Lopatic <thomas@…> (07/31/2017 05:01:38 PM)
Message:

Successfully loaded midas.abs from disk.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • emu/fdd.c

    r1efc42c rc5b6c90  
    2626#define N_CYL 80
    2727#define N_SID 2
    28 #define N_SEC 18
     28#define N_SEC 9
    2929#define SZ_SEC 512
    3030
    3131#define SZ_DISK (N_CYL * N_SID * N_SEC * SZ_SEC)
    3232
     33#define REG_COM_STAT 0
     34#define REG_TRA 1
     35#define REG_SEC 2
     36#define REG_DAT 3
     37
     38#define COM_REST 0x00
     39#define COM_SEEK 0x10
     40#define COM_SEEK_VER 0x14
     41#define COM_RD_SEC 0x80
     42#define COM_RD_SEC_MUL 0x90
     43#define COM_WR_SEC_WP 0xa0
     44#define COM_WR_SEC 0xa2
     45#define COM_INT 0xd0
     46#define COM_WR_TRA 0xf0
     47
     48#define COM_LAT_CYC 10
     49#define COM_EXE_CYC 10
     50
     51typedef enum {
     52        STEP_IDLE,
     53        STEP_PREP,
     54        STEP_EXEC
     55} step_t;
     56
     57typedef struct {
     58        int32_t reg_tra;
     59        int32_t reg_sec;
     60        int32_t reg_dat;
     61        int32_t sid;
     62        step_t step;
     63        int32_t com;
     64        int32_t cyc;
     65        uint8_t *dat;
     66        bool tra_0;
     67} state_t;
     68
     69static state_t state = {
     70                .reg_tra = 0, .reg_sec = 0, .reg_dat = 0, .sid = 0,
     71                .step = STEP_IDLE, .com = -1, .cyc = 0, .dat = NULL, .tra_0 = false
     72};
     73
    3374static uint8_t image[SZ_DISK];
     75
     76static const char *com_string(int32_t com)
     77{
     78        switch (com) {
     79        case COM_REST:
     80                return "COM_REST";
     81
     82        case COM_SEEK:
     83                return "COM_SEEK";
     84
     85        case COM_SEEK_VER:
     86                return "COM_SEEK_VER";
     87
     88        case COM_RD_SEC:
     89                return "COM_RD_SEC";
     90
     91        case COM_RD_SEC_MUL:
     92                return "COM_RD_SEC_MUL";
     93
     94        case COM_WR_SEC_WP:
     95                return "COM_WR_SEC_WP";
     96
     97        case COM_WR_SEC:
     98                return "COM_WR_SEC";
     99
     100        case COM_WR_TRA:
     101                return "COM_WR_TRA";
     102
     103        default:
     104                fail("unknown command 0x%02x", com);
     105        }
     106}
     107
     108static void stat_string(int32_t stat, char *buff) {
     109        buff[0] = 0;
     110
     111        if ((stat & 0x80) != 0) {
     112                strcat(buff, " mot_on");
     113        }
     114
     115        if ((stat & 0x04) != 0) {
     116                strcat(buff, " zero");
     117        }
     118
     119        if ((stat & 0x02) != 0) {
     120                strcat(buff, " dat_req");
     121        }
     122
     123        if ((stat & 0x01) != 0) {
     124                strcat(buff, " busy");
     125        }
     126}
     127
     128void fdd_set_side(int32_t sid)
     129{
     130        ver2("sid <- %d", sid);
     131        state.sid = sid;
     132}
     133
     134void fdd_set_sel(int32_t sel)
     135{
     136        ver2("sel <- %d", sel);
     137}
    34138
    35139void fdd_init(void)
     
    67171{
    68172        ver3("fdd exec");
     173
     174        switch (state.step) {
     175        case STEP_IDLE:
     176                break;
     177
     178        case STEP_PREP:
     179                ver3("prep %d", state.cyc);
     180                --state.cyc;
     181
     182                if (state.cyc == 0) {
     183                        ver2("exec %s", com_string(state.com));
     184                        state.step = STEP_EXEC;
     185                        state.cyc = COM_EXE_CYC;
     186                }
     187
     188                break;
     189
     190        case STEP_EXEC:
     191                ver3("exec %d", state.cyc);
     192                --state.cyc;
     193
     194                if (state.cyc == 0) {
     195                        ver2("idle %s", com_string(state.com));
     196                        state.step = STEP_IDLE;
     197                }
     198
     199                break;
     200        }
     201
    69202        return false;
    70203}
     
    72205uint32_t fdd_read(uint32_t off, int32_t sz)
    73206{
    74         ver2("fdd rd %u:%d", off, sz * 8);
    75         return 0;
     207        ver3("fdd rd %u:%d", off, sz * 8);
     208
     209        if (sz != 1 || off > 3) {
     210                fail("invalid fdd rd %u:%d", off, sz * 8);
     211        }
     212
     213        uint32_t rv;
     214
     215        switch (off) {
     216        case REG_COM_STAT:
     217                rv = 0x80; // motor on
     218
     219                if (state.step == STEP_EXEC) {
     220                        rv |= 0x01; // busy
     221
     222                        switch (state.com) {
     223                        case COM_RD_SEC:
     224                        case COM_RD_SEC_MUL:
     225                        case COM_WR_SEC:
     226                        case COM_WR_SEC_WP:
     227                                rv |= 0x02; // data request
     228                                break;
     229                        }
     230                }
     231
     232                if (state.tra_0) {
     233                        rv |= 0x04; // track zero
     234                }
     235
     236                char stat[100];
     237                stat_string((int32_t)rv, stat);
     238                ver3("stat -> 0x%02x%s", rv, stat);
     239                break;
     240
     241        case REG_TRA:
     242                rv = (uint32_t)state.reg_tra;
     243                ver2("tra -> %u", rv);
     244                break;
     245
     246        case REG_SEC:
     247                rv = (uint32_t)state.reg_sec;
     248                ver2("sec -> %u", rv);
     249                break;
     250
     251        case REG_DAT:
     252                if (state.step != STEP_EXEC ||
     253                                (state.com != COM_RD_SEC && state.com != COM_RD_SEC_MUL)) {
     254                        fail("unexpected data register read");
     255                }
     256
     257                rv = *state.dat;
     258                size_t addr = (size_t)(state.dat - image);
     259
     260                if ((addr & (SZ_SEC - 1)) == 0) {
     261                        ver2("addr 0x%06zx -> 0x%02x", addr, rv);
     262                }
     263                else {
     264                        ver3("addr 0x%06zx -> 0x%02x", addr, rv);
     265                }
     266
     267                ++state.dat;
     268                state.cyc = COM_EXE_CYC;
     269                break;
     270
     271        default:
     272                rv = 0;
     273                break;
     274        }
     275
     276        return rv;
    76277}
    77278
    78279void fdd_write(uint32_t off, int32_t sz, uint32_t val)
    79280{
    80         ver2("fdd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
    81 }
     281        ver3("fdd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
     282
     283        if (sz != 1 || off > 3) {
     284                fail("invalid fdd wr %u:%d", off, sz * 8);
     285        }
     286
     287        switch (off) {
     288        case REG_COM_STAT:
     289                ver2("com <- 0x%02x, tra %d, sid %d, sec %d",
     290                                val, state.reg_tra, state.sid, state.reg_sec);
     291
     292                state.com = (int32_t)val;
     293
     294                ver2("prep %s", com_string(state.com));
     295                state.step = STEP_PREP;
     296                state.cyc = COM_LAT_CYC;
     297
     298                switch (val) {
     299                case COM_REST:
     300                        state.reg_tra = 0;
     301                        state.tra_0 = true;
     302                        break;
     303
     304                case COM_SEEK:
     305                case COM_SEEK_VER:
     306                        state.reg_tra = state.reg_dat;
     307                        state.tra_0 = state.reg_tra == 0;
     308                        break;
     309
     310                case COM_RD_SEC:
     311                case COM_RD_SEC_MUL:
     312                case COM_WR_SEC:
     313                case COM_WR_SEC_WP: {
     314                        size_t sec_off = (size_t)(((state.reg_tra * N_SID + state.sid) * N_SEC +
     315                                        state.reg_sec - 1) * SZ_SEC);
     316                        state.dat = image + sec_off;
     317                        state.tra_0 = false;
     318                        break;
     319                }
     320
     321                case COM_INT:
     322                        state.step = STEP_IDLE;
     323                        state.com = -1;
     324                        state.cyc = 0;
     325                        state.dat = NULL;
     326                        state.tra_0 = false;
     327                        break;
     328
     329                case COM_WR_TRA:
     330                        state.tra_0 = false;
     331                        fail("format not yet supported");
     332                        break;
     333                }
     334
     335                break;
     336
     337        case REG_TRA:
     338                state.reg_tra = (int32_t)val;
     339                ver2("tra <- %u", val);
     340                break;
     341
     342        case REG_SEC:
     343                state.reg_sec = (int32_t)val;
     344                ver2("sec <- %u", val);
     345                break;
     346
     347        case REG_DAT:
     348                if (state.step == STEP_EXEC &&
     349                                (state.com == COM_WR_SEC || state.com == COM_WR_SEC_WP)) {
     350                        *state.dat = (uint8_t)val;
     351                        size_t addr = (size_t)(state.dat - image);
     352
     353                        if ((addr & (SZ_SEC - 1)) == 0) {
     354                                ver2("addr 0x%06zx <- 0x%02x", addr, val);
     355                        }
     356                        else {
     357                                ver3("addr 0x%06zx <- 0x%02x", addr, val);
     358                        }
     359
     360                        ++state.dat;
     361                        state.cyc = COM_EXE_CYC;
     362                }
     363                else {
     364                        state.reg_dat = (int32_t)val;
     365                        ver2("dat <- 0x%02x", val);
     366                }
     367
     368                break;
     369
     370        default:
     371                break;
     372        }
     373}
Note: See TracChangeset for help on using the changeset viewer.