|
@@ -10,6 +10,7 @@
|
|
|
#include "fw.h"
|
|
|
#include "io.h"
|
|
|
#include "abcio.h"
|
|
|
+#include "console.h"
|
|
|
#include "ff.h"
|
|
|
|
|
|
/* Option flags, mostly for debugging */
|
|
@@ -41,24 +42,29 @@ struct drive_state {
|
|
|
enum drive_flags force; /* Option to force flags */
|
|
|
};
|
|
|
|
|
|
-/* Per-controller state */
|
|
|
-struct ctl_state {
|
|
|
- struct abc_dev iodev;
|
|
|
- uint8_t k[4]; /* Command bytes */
|
|
|
+/* Fixed parameters for each controller */
|
|
|
+struct ctl_params {
|
|
|
uint8_t clustshift; /* log2(clustersize/256) */
|
|
|
uint8_t devsel; /* I/O device select */
|
|
|
uint16_t maxsectors; /* Maximum sectors for this controller */
|
|
|
uint8_t c, h, s; /* Disk geometry */
|
|
|
- uint8_t drives; /* Total drives present */
|
|
|
bool newaddr; /* "New addressing" */
|
|
|
const char name[4]; /* Name of controller (disk type) */
|
|
|
- bool initialized; /* Controller initialized */
|
|
|
#if INTERLEAVE
|
|
|
uint8_t ilmsk, ilfac; /* Software interleaving parea */
|
|
|
#endif
|
|
|
#if FORMAT_SUPPORT
|
|
|
bool fmtdata_i_buf; /* Use user-provided formatting data */
|
|
|
#endif
|
|
|
+} __attribute__((aligned(4)));
|
|
|
+
|
|
|
+/* Per-controller state */
|
|
|
+struct ctl_state {
|
|
|
+ struct abc_dev iodev;
|
|
|
+ const struct ctl_params *params;
|
|
|
+ uint8_t k[4]; /* Command bytes */
|
|
|
+ uint8_t drives; /* Total drives present */
|
|
|
+ bool initialized; /* Controller initialized */
|
|
|
volatile enum pending pending; /* Need to do I/O */
|
|
|
struct drive_state drv[8]; /* Per-drive state */
|
|
|
uint8_t buf[4][256]; /* 4 host buffers @ 256 bytes */
|
|
@@ -90,8 +96,7 @@ enum controller_types {
|
|
|
# define IL(mask, fac)
|
|
|
#endif
|
|
|
|
|
|
-/* This array is ~24K(!), probably needs to be moved to DRAM */
|
|
|
-static struct ctl_state __dram_data controllers[CONTROLLER_TYPES] = {
|
|
|
+static const struct ctl_params parameters[CONTROLLER_TYPES] = {
|
|
|
/*
|
|
|
* MOx: covers all of these formats:
|
|
|
* SSSD = 40×8×1 (80K, FD2/DD80),
|
|
@@ -138,6 +143,8 @@ static struct ctl_state __dram_data controllers[CONTROLLER_TYPES] = {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+static struct ctl_state __dram_bss controllers[CONTROLLER_TYPES];
|
|
|
+
|
|
|
static inline bool mounted(const struct drive_state *drv)
|
|
|
{
|
|
|
return !!(drv->flags & DF_MOUNTED);
|
|
@@ -157,10 +164,11 @@ static inline unsigned int cur_sector(const struct ctl_state *state)
|
|
|
{
|
|
|
uint8_t k2 = state->k[2], k3 = state->k[3];
|
|
|
|
|
|
- if (state->newaddr)
|
|
|
+ if (state->params->newaddr)
|
|
|
return (k2 << 8) + k3;
|
|
|
else
|
|
|
- return (((k2 << 3) + (k3 >> 5)) << state->clustshift) + (k3 & 31);
|
|
|
+ return (((k2 << 3) + (k3 >> 5)) << state->params->clustshift)
|
|
|
+ + (k3 & 31);
|
|
|
}
|
|
|
|
|
|
/* Get physical sector number, after interleaving */
|
|
@@ -195,10 +203,10 @@ static inline bool cur_sector_valid(const struct ctl_state *state)
|
|
|
{
|
|
|
uint8_t k3 = state->k[3];
|
|
|
|
|
|
- if (!state->newaddr && ((k3 & 31) >> state->clustshift))
|
|
|
+ if (!state->params->newaddr && ((k3 & 31) >> state->params->clustshift))
|
|
|
return false;
|
|
|
|
|
|
- return phys_sector(state) < state->maxsectors;
|
|
|
+ return phys_sector(state) < state->params->maxsectors;
|
|
|
}
|
|
|
|
|
|
static inline uint8_t *cur_buf(struct ctl_state *state)
|
|
@@ -255,7 +263,7 @@ name_to_drive(const char *drive)
|
|
|
for (int i = 0; i < CONTROLLER_TYPES; i++) {
|
|
|
struct ctl_state *state = &controllers[i];
|
|
|
|
|
|
- if (!memcmp(state->name, drive, 2))
|
|
|
+ if (!memcmp(state->params->name, drive, 2))
|
|
|
return &state->drv[ndrive];
|
|
|
}
|
|
|
|
|
@@ -306,6 +314,8 @@ static int mount_drive(struct drive_state *drv, struct ctl_state *state,
|
|
|
|
|
|
if (!(drv->flags & DF_MOUNTED))
|
|
|
return -1;
|
|
|
+
|
|
|
+ con_printf("abcdisk: %-3s = %s\n", drv->name, filename);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -313,12 +323,12 @@ static int mount_drive(struct drive_state *drv, struct ctl_state *state,
|
|
|
* beyond the end as bad.
|
|
|
*/
|
|
|
unsigned int filesec = f_size(&drv->file) >> 8;
|
|
|
- drv->sectors = (filesec < state->maxsectors) ? filesec : state->maxsectors;
|
|
|
+ drv->sectors = min(filesec, state->params->maxsectors);
|
|
|
|
|
|
/* Interleaving parameters */
|
|
|
#if INTERLEAVE
|
|
|
- drv->ilfac = state->ilfac;
|
|
|
- drv->ilmsk = state->ilmsk;
|
|
|
+ drv->ilfac = state->params->ilfac;
|
|
|
+ drv->ilmsk = state->params->ilmsk;
|
|
|
#endif
|
|
|
|
|
|
return 0;
|
|
@@ -380,11 +390,13 @@ static void init_drives(struct ctl_state *state)
|
|
|
unsigned int filesec;
|
|
|
char * const *pfx;
|
|
|
|
|
|
- snprintf(drv->name, sizeof drv->name, "%-.2s%c", state->name, i + '0');
|
|
|
+ snprintf(drv->name, sizeof drv->name, "%-.2s%c",
|
|
|
+ state->params->name, i + '0');
|
|
|
|
|
|
for (pfx = disk_pfx; *pfx; pfx++) {
|
|
|
char filename_buf[64];
|
|
|
- snprintf(filename_buf, sizeof filename_buf, "%s%s", *pfx, drv->name);
|
|
|
+ snprintf(filename_buf, sizeof filename_buf,
|
|
|
+ "%s%s", *pfx, drv->name);
|
|
|
|
|
|
if (!mount_drive(drv, state, filename_buf)) {
|
|
|
state->drives++;
|
|
@@ -473,7 +485,7 @@ static void do_next_command(struct ctl_state *state)
|
|
|
unsigned int fmtsec, filesec;
|
|
|
|
|
|
/* Sector count produced by format */
|
|
|
- fmtsec = state->maxsectors;
|
|
|
+ fmtsec = state->params->maxsectors;
|
|
|
|
|
|
/* For non-MO-drives, this seems to be internally generated */
|
|
|
memset(data, 0x40, 256);
|
|
@@ -607,19 +619,22 @@ void abcdisk_io_poll(void)
|
|
|
*/
|
|
|
void abcdisk_init(void)
|
|
|
{
|
|
|
+ static const struct abc_dev iodev_template = {
|
|
|
+ .callback_mask = IDLE_CALLBACK_MASK,
|
|
|
+ .status_first_out_mask = (uint8_t)~0x80,
|
|
|
+ .status_first_inp_mask = (uint8_t)~0x80,
|
|
|
+ .callback_out = abcdisk_callback_out,
|
|
|
+ .callback_inp = abcdisk_callback_inp,
|
|
|
+ .callback_cmd = abcdisk_callback_cmd
|
|
|
+ };
|
|
|
+
|
|
|
for (int i = 0; i < CONTROLLER_TYPES; i++) {
|
|
|
struct ctl_state *state = &controllers[i];
|
|
|
|
|
|
- /* Set up the bus device */
|
|
|
- memset(&state->iodev, 0, sizeof state->iodev);
|
|
|
- state->iodev.callback_mask = IDLE_CALLBACK_MASK;
|
|
|
- state->iodev.status_first_out_mask = (uint8_t)~0x80;
|
|
|
- state->iodev.status_first_inp_mask = (uint8_t)~0x80;
|
|
|
- state->iodev.callback_out = abcdisk_callback_out;
|
|
|
- state->iodev.callback_inp = abcdisk_callback_inp;
|
|
|
- state->iodev.callback_cmd = abcdisk_callback_cmd;
|
|
|
+ state->params = ¶meters[i];
|
|
|
+ state->iodev = iodev_template;
|
|
|
|
|
|
disk_reset_state(state);
|
|
|
- abc_register(&state->iodev, state->devsel);
|
|
|
+ abc_register(&state->iodev, state->params->devsel);
|
|
|
}
|
|
|
}
|