* on both Model 1 and Model 3
*
* Things To Do
- * - Set sector size and shift values in the config calls
- * - Use those in the I/O loop so we can do varying sector sizes
* - Handle double sided media (need to consider heads in the loop)
- * - Turn the step rate value into a step mask and use it in the asm code
* - Teach the asm code about density
* - Teach the asm code about double sided and maybe 128 byte sectors
* - Rework density handling
#define OPDIR_READ 1
#define OPDIR_WRITE 2
-#define FD_READ 0x80 /* 2797 needs 0x88, 1797 needs 0x80 */
-#define FD_WRITE 0xA0 /* Likewise A8 v A0 */
+#define FD_READ 0x80
+#define FD_WRITE 0xA0
static uint8_t motorct;
/* Extern as they live in common */
extern uint8_t fd_map, fd_tab[MAX_FD];
extern uint8_t fd_selected;
-extern uint8_t fd_cmd[7];
+extern uint8_t fd_cmd[9];
static struct fd_ops *fops;
},
};
+/* Consider a struct of this plus the fdcinfo to make the referencing
+ nice ? */
+static uint8_t shift[MAX_FD] = { 2, 2, 2, 2 };
+static uint16_t size[MAX_FD] = { 512, 512, 512, 512 };
+static uint8_t step[MAX_FD] = { 3, 3, 3, 3 };
+
/* Translate the drive into a selection. Assumes single sided on the M1 */
-static uint8_t selmap[4] = { 0x01, 0x02, 0x04, 0x08 };
+static uint8_t selmap[MAX_FD] = { 0x01, 0x02, 0x04, 0x08 };
+
+static uint8_t fd_select(uint8_t minor)
+{
+ uint8_t err = 0;
+ uint8_t tmp = 0;
+ /* Do we need to select the drive ? */
+ if (trs80_model != TRS80_MODEL3 || fd_selected != minor) {
+ kputs("sel");
+ /* Decide if we need double density */
+ if (fdc[minor].features & FDF_DD)
+ tmp |= 0x80;
+ err = fops->fd_motor_on(selmap[minor]|tmp);
+ if (!err)
+ fd_selected = minor;
+ }
+ return err;
+}
+
+static uint8_t do_fd_restore(uint8_t minor)
+{
+ if (fd_select(minor))
+ return 0xFF;
+ kputs("res1");
+ return fops->fd_restore(fd_tab + minor);
+}
static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
{
goto bad2;
/* Do we need to select the drive ? */
- if (trs80_model != TRS80_MODEL3 || fd_selected != minor) {
- uint8_t err;
- uint8_t tmp = 0;
- /* Decide if we need double density */
- if (f->features & FDF_DD)
- tmp |= 0x80;
- err = fops->fd_motor_on(selmap[minor]|tmp);
- if (err)
+ if (fd_select(minor))
goto bad;
- }
/* If we don't know where the head on this drive is then force
a seek */
- if (*driveptr == 0xFF)
+ if (*driveptr == 0xFF) {
+ kputs("res2");
if (err = fops->fd_restore(driveptr))
goto bad;
+ }
- /* Adjust for the block size if raw I/O. For now hard code 512 byte
- sectors but we need to sort this */
+ /* Adjust for actual media sector size */
fd_map = rawflag;
- if (rawflag && d_blkoff(BLKSHIFT))
+ if (rawflag) {
+ if (d_blkoff(7 + shift[minor]))
return -1;
+ } else {
+ udata.u_nblock <<= shift[minor];
+ udata.u_block <<= shift[minor];
+ }
- /* We only deal with single sided 512 byte/sector media for the moment */
+ /* We only deal with single sided media for the moment */
fd_cmd[0] = is_read ? FD_READ : FD_WRITE;
fd_cmd[3] = is_read ? OPDIR_READ: OPDIR_WRITE;
- fd_cmd[4] = ((uint16_t)udata.u_dptr) & 0xFF;
- fd_cmd[5] = ((uint16_t)udata.u_dptr) >> 8;
- fd_cmd[6] = 2; /* 0 128 1 256 2 512 : fixed for now */
+ fd_cmd[6] = shift[minor];
+ fd_cmd[7] = step[minor];
+ fd_cmd[8] = f->precomp;
while (ct < udata.u_nblock) {
/* For each block we need to load we work out where to find it */
fd_cmd[1] = udata.u_block / f->sectors;
fd_cmd[2] = udata.u_block % f->sectors;
+ fd_cmd[4] = ((uint16_t)udata.u_dptr) & 0xFF;
+ fd_cmd[5] = ((uint16_t)udata.u_dptr) >> 8;
/* Some single density media has sectors numbered from zero */
if (!(f->config & FDC_SEC0))
fd_cmd[2]++;
/* Reading 40 track media on an 80 track drive */
if (f->config & FDC_DSTEP)
fd_cmd[1] <<= 1;
+ kputs("op");
/* Now try the I/O */
for (tries = 0; tries < 4 ; tries++) {
err = fops->fd_op(driveptr);
}
if (tries == 4)
goto bad;
- fd_cmd[5]++; /* Move on 256 bytes in the buffer */
- fd_cmd[5]++; /* Move on 256 bytes in the buffer */
+ udata.u_dptr += size[minor];
ct++;
}
- return udata.u_nblock << 9;
+ return udata.u_nblock << (7 + shift[minor]);
bad:
kprintf("fd%d: error %x\n", minor, err);
bad2:
return -1;
}
/* No media ? */
- if (fops->fd_restore(fd_tab + minor) && !(flag & O_NDELAY)) {
+ if (do_fd_restore(minor) && !(flag & O_NDELAY)) {
udata.u_error = EIO;
return -1;
}
int fd_ioctl(uint8_t minor, uarg_t request, char *buffer)
{
+ uint8_t s;
+ uint16_t w;
switch(request) {
case FDIO_GETCAP:
return uput(fdcap + minor, buffer, sizeof(struct fdcinfo));
/* Ick.. but we are not portable code so we know how it packs */
if (uget(fdc + minor, buffer, 7))
return -1;
- /*FIXME when we sort DS meida */
- fdc[minor].heads = 1;
- /* TODO : steprate to masks */
fdc[minor].features &= fdcap[minor].features;
+ w = fdc[minor].features;
+ s = fdc[minor].steprate;
+ /* FIXME: WD1770 is different - consider undoubled model 1 */
+ /* Check chip and clock details */
+ /* WD1771 - 6 6 10 20 */
+ if (s >= 20)
+ s = 3;
+ else if (s >= 10)
+ s = 2;
+ else
+ s = 0;
+ step[minor] = s;
+ if (!(fdc[minor].config & FDC_PRECOMP))
+ fdc[minor].precomp = 255; /* Never precomp */
+ switch(w &= FDF_SECSIZE) {
+ case 128:
+ s = 0;
+ break;
+ case 256:
+ s = 1;
+ break;
+ default:
+ case 512:
+ s = 2;
+ break;
+ }
+ shift[minor] = s;
+ size[minor] = w;
/* Force reconfiguration */
fd_tab[minor] = 0xFF;
fd_selected = 255;
case FDIO_FMTTRK:
return -1;
case FDIO_RESTORE:
- return fops->fd_restore(fd_tab + minor);
+ fd_selected = 255; /* Force a re-configure */
+ return do_fd_restore(minor);
}
return -1;
}
; Based on the 6809 code
;
; FIXME: better drive spin up wait
-; FIXME: tandy doubler
+; FIXME: doublers
; FIXME: correct step rates (per drive ?)
; FIXME: precompensation ??
; FIXME: 512 byte sector support
+; FIXME: sector size setting
+; FIXME: improve SD/DD handling
;
.globl _fd_restore
.globl _fd_operation
SECTOR .equ 2
DIRECT .equ 3 ; 0 = read 2 = write 1 = status
DATA .equ 4
+SIZE .equ 6 ; For now 1 = 256 2 = 512
+STEP .equ 7 ; Step rate
+COMP .equ 8 ; Write compensation
.area _COMMONMEM
;
; Need to seek the disk
;
ld hl,#FDCREG
- ld a, #0x18 ; seek FIXME: need to set step rate
+ ld a, #0x18
+ or STEP(ix)
ld (hl), a
call waitcmd
and #0x18 ; error bits
ld (FDCSEC), a
xor a
ld (FDCTRK), a
- ld a, #0x0C
+ ld a, #0x0C ; FIXME: seek rate ??
ld (FDCREG), a ; restore
ld a, #0xFF
ld (hl), a ; Zap track pointer
ld (LATCHD0), a ; Selects the actual disk we want
ld d,a ; Save latch value
rl c ; Bit 7 into C
+ ; FIXME: Tandy DD support
ld a,#0xFE ; Figure out the density
adc a,#0 ; FE or FF according to density
di
_fd_tab:
.db 0xFF, 0xFF, 0xFF, 0xFF
_fd_cmd:
- .ds 7
+ .ds 9