summaryrefslogtreecommitdiff
path: root/chips/fdc_82077_hdw.c
diff options
context:
space:
mode:
authorThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
committerThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
commitf07a4c844da9f0ecae5bbee1ab94be56505f26f7 (patch)
tree12b07c7e578fc1a5f53dbfde2632408491ff2a70 /chips/fdc_82077_hdw.c
Initial source
Diffstat (limited to 'chips/fdc_82077_hdw.c')
-rw-r--r--chips/fdc_82077_hdw.c821
1 files changed, 821 insertions, 0 deletions
diff --git a/chips/fdc_82077_hdw.c b/chips/fdc_82077_hdw.c
new file mode 100644
index 0000000..f52da83
--- /dev/null
+++ b/chips/fdc_82077_hdw.c
@@ -0,0 +1,821 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: fdi_82077_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Driver for the Intel 82077 Floppy Disk Controller.
+ */
+
+#include <fd.h>
+#if NFD > 0
+
+#include <mach/std_types.h>
+#include <machine/machspl.h>
+#include <chips/busses.h>
+
+#include <chips/fdc_82077.h>
+#include <platforms.h>
+
+/* ---- */
+#include <device/param.h>
+#include <device/io_req.h>
+#include <device/device_types.h>
+#include <device/disk_status.h>
+#define UNITNO(d) ((d)>>5)
+#define SLAVENO(d) (((d)>>3)&0x3)
+#define PARAMNO(d) ((d)&0x7)
+/* ---- */
+
+#ifdef MAXINE
+
+/* we can only take one */
+#define MAX_DRIVES 1
+
+#define my_fdc_type fdc_82077aa
+#define the_fdc_type fd->fdc_type
+/* later: #define the_fdc_type my_fdc_type */
+
+/* Registers are read/written as words, byte 0 */
+/* padding is to x40 boundaries */
+typedef struct {
+ volatile unsigned int fd_sra; /* r: status register A */
+ int pad0[15];
+ volatile unsigned int fd_srb; /* r: status register B */
+ int pad1[15];
+ volatile unsigned int fd_dor; /* rw: digital output reg */
+ int pad2[15];
+ volatile unsigned int fd_tdr; /* rw: tape drive register */
+ int pad3[15];
+ volatile unsigned int fd_msr; /* r: main status register */
+/*#define fd_dsr fd_msr; /* w: data rate select reg */
+ int pad4[15];
+ volatile unsigned int fd_data; /* rw: fifo */
+ int pad5[15];
+ volatile unsigned int fd_xxx; /* --reserved-- */
+ int pad6[15];
+ volatile unsigned int fd_dir; /* r: digital input reg */
+/*#define fd_ccr fd_dir; /* w: config control reg */
+} fd_padded_regmap_t;
+
+#define machdep_reset_8272a(f,r)
+
+#else /* MAXINE */
+
+/* Pick your chip and padding */
+#define my_fdc_type fdc_8272a
+#define the_fdc_type my_fdc_type
+
+#define fd_padded_regmap_t fd_8272a_regmap_t
+
+#define machdep_reset_8272a(f,r) 1
+
+#endif /* MAXINE */
+
+
+#ifndef MAX_DRIVES
+#define MAX_DRIVES DRIVES_PER_FDC
+#endif
+
+/*
+ * Autoconf info
+ */
+
+static vm_offset_t fd_std[NFD] = { 0 };
+static struct bus_device *fd_info[NFD];
+static struct bus_ctlr *fd_minfo[NFD];
+static int fd_probe(), fd_slave(), fd_go();
+static void fd_attach();
+
+struct bus_driver fd_driver =
+ { fd_probe, fd_slave, fd_attach, fd_go, fd_std, "fd", fd_info,
+ "fdc", fd_minfo, /*BUS_INTR_B4_PROBE*/};
+
+/*
+ * Externally visible functions
+ */
+int fd_intr(); /* kernel */
+
+/*
+ * Media table
+ *
+ * Cyls,Sec,spc,part,Mtype,RWFpl,FGpl
+ */
+typedef struct {
+ unsigned char d_cylperunit;
+ unsigned char d_secpercyl;
+ unsigned short d_secperunit;
+ unsigned char d_secpertrk;
+ unsigned char d_gpl;
+ unsigned char d_fgpl;
+ unsigned char d_xfer_rate;
+} fd_params_t;
+
+fd_params_t fd_params[8] = {
+ {80, 18, 1440, 9, 0x2a, 0x50, FD_DSR_DD_250}, /* [0] 3.50" 720 Kb */
+ {80, 36, 2880, 18, 0x1b, 0x6c, FD_DSR_DD_500}, /* [1] 3.50" 1.44 Meg */
+ {40, 18, 720, 9, 0x2a, 0x50, FD_DSR_DD_250}, /* [2] 5.25" 360 Kb */
+ {80, 30, 2400, 15, 0x1b, 0x54, FD_DSR_DD_500}, /* [3] 5.25" 1.20 Meg */
+};
+
+/*
+ * Software status of chip
+ */
+struct fd_softc {
+ fd_padded_regmap_t *regs;
+ char fdc_type;
+ char fdc_mode;
+ char messed_up;
+ char slave_active;
+ struct slave_t {
+ io_req_t ior;
+ decl_simple_lock_data(,slave_lock)
+
+ /* status at end of last command */
+ unsigned char st0;
+ unsigned char st1;
+ unsigned char st2;
+ unsigned char c;
+ unsigned char h;
+ unsigned char r;
+ unsigned char n;
+ unsigned char st3;
+ /* ... */
+ unsigned char medium_status;
+# define ST_MEDIUM_PRESENT 1
+# define ST_MEDIUM_KNOWN 2
+ char last_command;
+ char bytes_expected;
+ fd_params_t *params;
+
+ } slave_status[DRIVES_PER_FDC];
+} fd_softc_data[NFD];
+
+typedef struct fd_softc *fd_softc_t;
+
+fd_softc_t fd_softc[NFD];
+
+static char *chip_names[4] = { "8272-A", "82072", "82077-AA", 0 };
+static char *mode_names[4] = { "PC AT", "PS/2", "Model 30", 0 };
+
+/*
+ * Probe chip to see if it is there
+ */
+static fd_probe (reg, ctlr)
+ vm_offset_t reg;
+ struct bus_ctlr *ctlr;
+{
+ int unit = ctlr->unit;
+ fd_softc_t fd;
+ fd_padded_regmap_t *regs;
+
+ /*
+ * See if we are here
+ */
+ if (check_memory(reg, 0)) {
+ /* no rides today */
+ return 0;
+ }
+
+ fd = &fd_softc_data[unit];
+ fd_softc[unit] = fd;
+
+ regs = (fd_padded_regmap_t *)reg;
+ fd->regs = regs;
+ fd->fdc_type = my_fdc_type;
+
+ fd_reset(fd);
+
+ if (the_fdc_type == fdc_82077aa) {
+ /* See if properly functioning */
+ unsigned char temp = FD_CMD_VERSION;
+ if (!fd_go(fd, 0, &temp, 1, 1))
+ return 0; /* total brxage */
+ if (!fd_get_result(fd, &temp, 1, FALSE))
+ return 0; /* partial brxage */
+ if (temp != FD_VERSION_82077AA)
+ printf( "{ %s x%x } ",
+ "Accepting non-82077aa version id",
+ temp);
+ }
+
+ printf("%s%d: %s chip controller",
+ ctlr->name, ctlr->unit, chip_names[fd->fdc_type]);
+ if (the_fdc_type == fdc_82077aa)
+ printf(" in %s mode", mode_names[fd->fdc_mode]);
+ printf(".\n");
+
+ return 1;
+}
+
+/* See if we like this slave */
+static fd_slave(ui, reg)
+ struct bus_device *ui;
+ vm_offset_t reg;
+{
+ int slave = ui->slave;
+ fd_softc_t fd;
+ unsigned char sns[2];
+
+ if (slave >= MAX_DRIVES) return 0;
+
+ fd = fd_softc[ui->ctlr];
+
+ sns[0] = FD_CMD_SENSE_DRIVE_STATUS;
+ sns[1] = slave & 0x3;
+ if (the_fdc_type == fdc_82072)
+ sns[1] |= FD_CMD_SDS_NO_MOT;
+ if (!fd_go(fd, slave, sns, 2, 1)) return 0;
+ if (!fd_get_result(fd, sns, 1, FALSE)) return 0;
+
+ fd->slave_status[slave].st3 = sns[0];
+
+ return 1;
+}
+
+static void
+fd_attach (ui)
+ struct bus_device *ui;
+{
+ /* Attach a slave */
+}
+
+static boolean_t
+fd_go(fd, slave, cmd, cmdlen, reply_count)
+ fd_softc_t fd;
+ unsigned char cmd[];
+{
+
+ /* XXX check who active, enque ifnot */
+
+ fd->slave_active = slave;
+ fd->slave_status[slave].bytes_expected = reply_count;
+ fd->slave_status[slave].last_command = *cmd;
+ return fd_command(fd, cmd, cmdlen);
+}
+
+fd_intr (unit, spllevel)
+{
+ fd_softc_t fd;
+ fd_padded_regmap_t *regs;
+ unsigned char msr;
+ register struct slave_t *slv;
+
+
+ splx(spllevel);
+
+ fd = fd_softc[unit];
+ regs = fd->regs;
+
+ /* did polling see a media change */
+ /* busy bit in msr sez ifasync or not */
+
+ msr = regs->fd_msr;
+ if ((msr & (FD_MSR_RQM|FD_MSR_DIO)) == (FD_MSR_RQM|FD_MSR_DIO)) {
+
+ /* result phase */
+*(unsigned int *)0xbc040100 &= ~0x00600000;
+
+ slv = &fd->slave_status[fd->slave_active];
+ fd_get_result(fd, &slv->st0, slv->bytes_expected, FALSE);
+ fd_start(fd, fd->slave_active, TRUE);
+ return;
+ }
+ /* async interrupt, either seek complete or media change */
+ while (1) {
+ unsigned char st[2];
+ register int slave, m;
+
+ *st = FD_CMD_SENSE_INT_STATUS;
+ fd_command(fd, st, 1);
+
+ fd_get_result(fd, st, 2, FALSE);
+
+ slave = *st & FD_ST0_DS;
+ slv = &fd->slave_status[slave];
+ slv->c = st[1];
+
+ switch (*st & FD_ST0_IC_MASK) {
+
+ case FD_ST0_IC_OK:
+/* we get an FD_ST0_SE for RECALIBRATE. Wait for it or discard ? */
+
+ case FD_ST0_IC_AT:
+
+ case FD_ST0_IC_BAD_CMD:
+ return;
+
+ case FD_ST0_IC_AT_POLL:
+ m = slv->medium_status;
+ if (m & ST_MEDIUM_PRESENT)
+ m &= ~ST_MEDIUM_PRESENT;
+ else
+ m |= ST_MEDIUM_PRESENT;
+ slv->medium_status = m;
+ }
+ }
+}
+
+/*
+ * Non-interface functions and utilities
+ */
+
+fd_reset(fd)
+ fd_softc_t fd;
+{
+ register fd_padded_regmap_t *regs;
+
+ regs = fd->regs;
+
+ /*
+ * Reset the chip
+ */
+ if (the_fdc_type == fdc_82072)
+ /* Fix if your box uses an external PLL */
+ regs->fd_dsr = FD_DSR_RESET | FD_DSR_EPLL;
+ else if (the_fdc_type == fdc_82077aa)
+ regs->fd_dor = 0;
+ else
+ machdep_reset_8272a(fd, regs);
+
+ delay(5); /* 4usecs in specs */
+
+ /*
+ * Be smart with the smart ones
+ */
+ if (the_fdc_type == fdc_82077aa) {
+
+ /*
+ * See in which mood we are (it cannot be changed)
+ */
+ int temp;
+
+ /* Take chip out of hw reset */
+ regs->fd_dor = FD_DOR_ENABLE | FD_DOR_DMA_GATE;
+ delay(10);
+
+ /* what do we readback from the DIR register as datarate ? */
+ regs->fd_ccr = FD_DSR_SD_125;
+ delay(10);
+
+ temp = regs->fd_dir;
+ if ((temp & 0x7) == FD_DSR_SD_125)
+ fd->fdc_mode = mod30_mode;
+ else if ((temp & (FD_DIR_ones | FD_DIR_DR_MASK_PS2)) ==
+ ((FD_DSR_SD_125 << FD_DIR_DR_SHIFT_PS2) | FD_DIR_ones))
+ fd->fdc_mode = ps2_mode;
+ else
+ /* this assumes tri-stated bits 1&2 read the same */
+ fd->fdc_mode = at_mode;
+
+ }
+
+ /*
+ * Send at least 4 sense interrupt cmds, one per slave
+ */
+ {
+
+ unsigned char sns, st[2];
+ int i, nloops;
+
+ sns = FD_CMD_SENSE_INT_STATUS;
+ i = nloops = 0;
+
+ do {
+ nloops++;
+
+ (void) fd_command(fd, &sns, 1);
+
+ st[0] = 0; /* in case bad status */
+ (void) fd_get_result(fd, st, 2, TRUE);
+
+ if ((st[0] & FD_ST0_IC_MASK) == FD_ST0_IC_AT_POLL) {
+ register int slave;
+
+ slave = st[0] & FD_ST0_DS;
+ fd->slave_status[slave].st0 = st[0];
+ fd->slave_status[slave].c = st[1];
+ i++;
+ }
+ } while ( (nloops < 30) &&
+ ((i < 4) || (st[0] != FD_ST0_IC_BAD_CMD)) );
+
+ /* sanity check */
+ if (nloops == 30) {
+ (void) fd_messed_up(fd);
+ return;
+ }
+ }
+
+ /*
+ * Install current parameters
+ */
+ if (the_fdc_type != fdc_8272a) {
+
+ unsigned char cnf[4];
+
+ /* send configure command to turn polling off */
+ cnf[0] = FD_CMD_CONFIGURE;
+ cnf[1] = 0x60; /* moff 110 */
+ cnf[2] = 0x48; /* eis, poll, thr=8 */
+ cnf[3] = 0;
+ if (!fd_command(fd, cnf, 4))
+ return;
+ /* no status */
+ }
+
+ /*
+ * Send specify to select defaults
+ */
+ {
+ unsigned char sfy[3];
+
+ sfy[0] = FD_CMD_SPECIFY;
+#if 0
+ sfy[1] = (12 << 4) | 7; /* step 4, hut 112us @500 */
+ sfy[2] = 2 << 1; /* hlt 29us @500 */
+#else
+ sfy[1] = (13 << 4) | 15;
+ sfy[2] = 1 << 1;
+#endif
+ (void) fd_command(fd, sfy, 3);
+ /* no status */
+ }
+}
+
+#define FD_MAX_WAIT 1000
+
+boolean_t
+fd_command(fd, cmd, cmd_len)
+ fd_softc_t fd;
+ char *cmd;
+{
+ register fd_padded_regmap_t *regs;
+
+ regs = fd->regs;
+
+ while (cmd_len > 0) {
+ register int i, s;
+
+ /* there might be long delays, so we pay this price */
+ s = splhigh();
+ for (i = 0; i < FD_MAX_WAIT; i++)
+ if ((regs->fd_msr & (FD_MSR_RQM|FD_MSR_DIO)) ==
+ FD_MSR_RQM)
+ break;
+ else
+ delay(10);
+ if (i == FD_MAX_WAIT) {
+ splx(s);
+ return fd_messed_up(fd);
+ }
+ regs->fd_data = *cmd++;
+ splx(s);
+ if (--cmd_len) delay(12);
+ }
+
+ return TRUE;
+}
+
+boolean_t
+fd_get_result(fd, st, st_len, ignore_errors)
+ fd_softc_t fd;
+ char *st;
+{
+ register fd_padded_regmap_t *regs;
+
+ regs = fd->regs;
+
+ while (st_len > 0) {
+ register int i, s;
+
+ /* there might be long delays, so we pay this price */
+ s = splhigh();
+ for (i = 0; i < FD_MAX_WAIT; i++)
+ if ((regs->fd_msr & (FD_MSR_RQM|FD_MSR_DIO)) ==
+ (FD_MSR_RQM|FD_MSR_DIO))
+ break;
+ else
+ delay(10);
+ if (i == FD_MAX_WAIT) {
+ splx(s);
+ return (ignore_errors) ? FALSE : fd_messed_up(fd);
+ }
+ *st++ = regs->fd_data;
+ splx(s);
+ st_len--;
+ }
+
+ return TRUE;
+}
+
+
+boolean_t
+fd_messed_up(fd)
+ fd_softc_t fd;
+{
+ fd->messed_up++;
+ printf("fd%d: messed up, disabling.\n", fd - fd_softc_data);
+ /* here code to
+ ior->error = ..;
+ restart
+ */
+ return FALSE;
+}
+
+/*
+ * Debugging aids
+ */
+
+fd_state(unit)
+{
+ fd_softc_t fd = fd_softc[unit];
+ fd_padded_regmap_t *regs;
+
+ if (!fd || !fd->regs) return 0;
+ regs = fd->regs;
+ if (the_fdc_type == fdc_8272a)
+ printf("msr %x\n", regs->fd_msr);
+ else
+ printf("sra %x srb %x dor %x tdr %x msr %x dir %x\n",
+ regs->fd_sra, regs->fd_srb, regs->fd_dor,
+ regs->fd_tdr, regs->fd_msr, regs->fd_dir);
+}
+
+#endif
+
+/* to be moved in separate file, or the above modified to live with scsi */
+
+fd_open(dev, mode, ior)
+ int dev;
+ dev_mode_t mode;
+ io_req_t ior;
+{
+ unsigned char cmd[2];
+ fd_softc_t fd;
+ int slave;
+
+ fd = fd_softc[UNITNO(dev)];
+ slave = SLAVENO(dev);
+
+ /* XXX find out what medium we have, automagically XXX */
+ /* fornow, set params depending on minor */
+ fd->slave_status[slave].params = &fd_params[PARAMNO(dev)];
+
+ /* XXXYYYXXXYYY SEND CONFIGURE if params changed */
+
+ /* Turn motor on */
+ if (the_fdc_type == fdc_82072) {
+
+ cmd[0] = FD_CMD_MOTOR_ON_OFF | FD_CMD_MOT_ON |
+ ((slave << FD_CMD_MOT_DS_SHIFT) & FD_CMD_MOT_DS);
+ (void) fd_go(fd, slave, cmd, 1, 0);
+ /* no status */
+
+ } else if (the_fdc_type == fdc_82077aa) {
+
+ fd->regs->fd_dor |= ((1<<slave)<<4);
+ }
+
+ /* recalibrate to track 0 */
+ cmd[0] = FD_CMD_RECALIBRATE;
+ cmd[1] = slave;
+ if (!fd_go(fd, slave, cmd, 2, 0))
+ return D_DEVICE_DOWN;
+ /* will generate a completion interrupt */
+
+ /* if not writeable return D_READ_ONLY ? */
+
+ return D_SUCCESS;
+}
+
+fd_close(dev)
+ int dev;
+{
+ fd_softc_t fd;
+ register int slave;
+ unsigned char cmd[2];
+
+ slave = SLAVENO(dev);
+ fd = fd_softc[UNITNO(dev)];
+
+ /* do not delete media info, do that iff interrupt sez changed */
+
+ /* Turn motor off */
+ if (the_fdc_type == fdc_82072) {
+
+ cmd[0] = FD_CMD_MOTOR_ON_OFF |
+ ((slave << FD_CMD_MOT_DS_SHIFT) & FD_CMD_MOT_DS);
+ (void) fd_go(fd, 0, cmd, 1, 0);
+ /* no status */
+
+ } else if (the_fdc_type == fdc_82077aa) {
+
+ fd->regs->fd_dor &= ~((1<<slave)<<4);
+ }
+ return D_SUCCESS;
+}
+
+fd_strategy(ior)
+ io_req_t ior;
+{
+#if 0
+ if (ior->io_op & IO_READ)
+ bzero(ior->io_data, ior->io_count);
+ iodone(ior);
+#else
+ struct slave_t *slv;
+ fd_softc_t fd;
+ unsigned int i, rec, max, dev;
+ fd_params_t *params;
+
+ /* readonly */
+
+ dev = ior->io_unit;
+
+ /* only one partition */
+ fd = fd_softc[UNITNO(dev)];
+ slv = &fd->slave_status[SLAVENO(dev)];
+ params = slv->params;
+ max = params->d_secperunit;
+ rec = ior->io_recnum;
+ i = btodb(ior->io_count + DEV_BSIZE - 1);
+ if (((rec + i) > max) || (ior->io_count < 0)) {
+ ior->io_error = D_INVALID_SIZE;
+ ior->io_op |= IO_ERROR;
+ ior->io_residual = ior->io_count;
+ iodone(ior);
+ return;
+ }
+
+ ior->io_residual = rec / params->d_secpercyl;
+
+ /*
+ * Enqueue operation
+ */
+ i = splbio();
+ simple_lock(&slv->slave_lock);
+ if (slv->ior) {
+ disksort(slv->ior, ior);
+ simple_unlock(&slv->slave_lock);
+ } else {
+ ior->io_next = 0;
+ slv->ior = ior;
+ simple_unlock(&slv->slave_lock);
+ fd_start(fd, SLAVENO(dev), FALSE);
+ }
+ splx(i);
+#endif
+}
+
+fd_start(fd, slave, done)
+ boolean_t done;
+ fd_softc_t fd;
+{
+ register io_req_t ior;
+ struct slave_t *slv;
+
+ slv = &fd->slave_status[slave];
+ if ((ior = slv->ior) == 0)
+ return;
+
+ if (done) {
+ /* .. errors .. */
+ /* .. partial xfers .. */
+
+ /* dequeue next one */
+ {
+ io_req_t next;
+
+ simple_lock(&slv->target_lock);
+ next = ior->io_next;
+ slv->ior = next;
+ simple_unlock(&slv->target_lock);
+
+ iodone(ior);
+ if (next == 0)
+ return;
+
+ ior = next;
+ }
+ }
+
+#ifdef no_eis
+ if (slv->c != ior->io_residual) SEEK_it;
+#endif
+
+/* setup dma */
+#if 1
+ if (ior->io_op & IO_READ) /* like SCSI */
+#else
+ if ((ior->io_op & IO_READ) == 0)
+#endif
+ {
+ *(unsigned int *)0xbc040100 |= 0x00200000 | 0x00400000;
+ } else {
+ *(unsigned int *)0xbc040100 &= ~0x00400000;
+ *(unsigned int *)0xbc040100 |= 0x00200000;
+ }
+ *(unsigned int *)0xbc040070 = (((unsigned int)kvtophys(ior->io_data))>>2)<<5;
+ *(unsigned int *)0xbc0401a0 = 13;
+
+#ifdef no_eis
+ if (slv->c == ior->io_residual) {
+#else
+ {
+#endif
+ unsigned char cmd[9];
+ unsigned char head, sec;
+ fd_params_t *params;
+
+ params = slv->params;
+
+ fd->regs->fd_dsr = params->d_xfer_rate;
+
+ sec = ior->io_recnum % params->d_secpercyl;
+ head = sec / params->d_secpertrk;
+ sec = (sec % params->d_secpertrk);
+
+ cmd[0] = (ior->io_op & IO_READ) ?
+ FD_CMD_MT | FD_CMD_MFM | FD_CMD_READ_DATA :
+ FD_CMD_MT | FD_CMD_MFM | FD_CMD_WRITE_DATA;
+ cmd[1] = (head << 2) | slave;
+ cmd[2] = ior->io_residual;
+ cmd[3] = head;
+ cmd[4] = sec + 1; /* 0 starts at 1 :-) */
+ cmd[5] = 0x2; /* 512 byte sectors */
+ cmd[6] = params->d_secpertrk;
+ cmd[7] = params->d_gpl;
+ cmd[8] = 0xff;
+
+ fd_go( fd, slave, cmd, 9, 7);
+
+ }
+}
+
+extern minphys();
+
+fd_read(dev, ior)
+ int dev;
+ io_req_t ior;
+{
+ return block_io(fd_strategy, minphys, ior);
+}
+
+int fdc_write_enable = 1;
+
+fd_write(dev, ior)
+ int dev;
+ io_req_t ior;
+{
+/* check if writeable */
+
+if (fdc_write_enable)
+ return block_io(fd_strategy, minphys, ior);
+else return D_SUCCESS;
+}
+
+fd_set_status(dev, flavor, status, status_count)
+ int dev;
+ int flavor;
+ dev_status_t status;
+ unsigned int *status_count;
+{
+ printf("fdc_set_status(%x, %x, %x, %x)", dev, flavor, status, status_count);
+ return D_SUCCESS;
+}
+
+fd_get_status(dev, flavor, status, status_count)
+ int dev;
+ int flavor;
+ dev_status_t status;
+ unsigned int status_count;
+{
+ printf("fdc_get_status(%x, %x, %x, %x)", dev, flavor, status, status_count);
+ return D_SUCCESS;
+}
+