コード例 #1
0
ファイル: blkdev.c プロジェクト: willsowerbutts/FUZIX
static int blkdev_transfer(uint8_t minor, uint8_t rawflag)
{
    uint8_t partition, n;
    uint16_t count = 0;

    /* we trust that blkdev_open() has already verified that this minor number is valid */
    blk_op.blkdev = &blkdev_table[minor >> 4];
    partition = minor & 0x0F;

    blk_op.is_user = rawflag;
    switch(rawflag){
        case 0:
            /* read single 512-byte sector to buffer in kernel memory */
            break;
        case 1:
            /* read some number of 512-byte sectors directly to user memory */
            if (d_blkoff(BLKSHIFT))
                return -1;
            break;
#ifdef SWAPDEV
        case 2:
            blk_op.swap_page = swappage;
            break;
#endif
        default:
            goto xferfail;
    }
    /* FIXME: these should go away now but we need to make u_block some
       kind of raw blkno_t that can be 32bit optionally */
    blk_op.nblock = udata.u_nblock;
    blk_op.lba = udata.u_block;
    blk_op.addr = udata.u_dptr;

    if(partition == 0){
	/* partition 0 is the whole disk and requires no translation */
	if(blk_op.lba >= blk_op.blkdev->drive_lba_count)
	    goto xferfail;
    }else{
	/* partitions 1+ require us to add in an offset */
	if(blk_op.lba >= blk_op.blkdev->lba_count[partition-1])
	    goto xferfail;

	blk_op.lba += blk_op.blkdev->lba_first[partition-1];
    }

    while(blk_op.nblock){
        n = blk_op.blkdev->transfer();
        if(n == 0)
            goto xferfail;
        blk_op.nblock -= n;
        count += n;
	blk_op.addr += n * BLKSIZE;
	blk_op.lba += n;
    }

    return count << BLKSHIFT; /* 10/10, would transfer sectors again */
xferfail:
    udata.u_error = EIO;
    return -1;
}
コード例 #2
0
ファイル: devrd.c プロジェクト: JamesLinus/FUZIX
static int rd_transfer(bool is_read, uint8_t rawflag)
{
    uint16_t dptr;
    int ct = 0;
    int map;
    const uint8_t *p = kmap;

    if(rawflag) {
        p = (const uint8_t *)&udata.u_page;
        if (d_blkoff(BLKSHIFT))
            return -1;
    }

    udata.u_block += 2*320;	/* ramdisc starts at 320K in */

    dptr = (uint16_t)udata.u_dptr;

    while (ct < udata.u_nblock) {
        /* Pass the page to map for the data */
        map = p[(dptr >> 14)];
        rd_memcpy(is_read, map, dptr, udata.u_block);
        udata.u_block++;
        ct++;
        dptr += BLKSIZE;
    }
    return ct << BLKSHIFT;
}
コード例 #3
0
ファイル: devrd.c プロジェクト: davidgiven/FUZIX
/* implements both rd_read and rd_write */
int rd_transfer(uint8_t minor, uint8_t rawflag, uint8_t flag)
{
    used(flag);

    /* check device exists; do not allow writes to ROM */
    if (minor == RD_MINOR_ROM && rd_reverse) {
        udata.u_error = EROFS;
        return -1;
    } else {
        rd_src_address = dev_start[minor];

        if (rawflag) {
            if (d_blkoff(9))
                return -1;
            /* rawflag == 1, userspace transfer */
        }
        rd_dst_userspace = rawflag;

        rd_dst_address = (uint16_t)udata.u_dptr;
        rd_src_address += ((uint32_t)udata.u_block) << BLKSHIFT;

        if (rd_src_address >= dev_limit[minor]) {
           udata.u_error = EIO;
           return -1;
        }
    }
    rd_platform_copy();
    return rd_cpy_count;
}
コード例 #4
0
ファイル: devfd.c プロジェクト: EtchedPixels/FUZIX
static int fd_transfer(bool is_read, uint_fast8_t minor, uint_fast8_t rawflag)
{
    uint16_t dptr;
    uint16_t ct = 0;
    uint_fast8_t st;

    fd_page = 0;
    if(rawflag == 1) {
        if (d_blkoff(7))
            return -1;
        fd_page = udata.u_page;

#ifdef SWAPDEV
    } else if (rawflag == 2) {		/* Swap device special */
        fd_page = swappage;		/* Acting on this page */
        /*
         *	In the z80pack case this is simpler than usual. Be very
         *	careful how you implement the swap device. On most platforms
         *	we have user space in part of the "common" which means you
         *	must be prepared to switch common segment as well during
         *	a swap, or to perform mapping games using the banks
         */
        udata.u_nblock *= (BLKSIZE / 128);
        /* Limits us to 2^14 blocks (16MB) */
        udata.u_block <<= 2;
#endif
    } else { /* rawflag == 0 */
        udata.u_nblock = BLKSIZE / 128;		/* BLKSIZE bytes implied */
        /* Limits us to 2^14 blocks (16MB) */
        udata.u_block <<= 2;
    }
    /* Read the disk in four sector chunks. FIXME We ought to cache the geometry
       and just bump sector checking for a wrap. */

    fd_dma = (uint16_t)udata.u_dptr;
    while (ct < udata.u_nblock) {
        fd_drive = minor;
        fd_geom(minor, udata.u_block);
        /* The Z80pack DMA uses the current MMU mappings... beware that
         * is odd - but most hardware would be PIO (inir/otir etc) anyway */
        fd_cmd = 1 - is_read;

        st = fd_op();
        /* Real disks would need retries */
        if (st) {
            kprintf("fd%d: block %d, error %d\n", minor, udata.u_block, st);
            break;
        }
        udata.u_block++;
        ct++;
        fd_dma += 128;
    }
    return ct << 7;
}
コード例 #5
0
ファイル: devfd.c プロジェクト: davidgiven/FUZIX
static int devfd_transfer(bool is_read, uint8_t is_raw)
{
    int ct = 0;
    int tries;
    int blocks = udata.u_nblock;
    uint16_t lba = udata.u_block;

    // kprintf("[%s %d @ %x : %d:%x]\n", is_read ? "read" : "write",
    //     blocks, lba, is_raw, udata.u_dptr);
    // if (!is_read)
    //     return blocks << BLKSHIFT;

    if (is_raw && d_blkoff(BLKSHIFT))
        return -1;

    fd_select(0);
    fd765_is_user = is_raw;
    fd765_buffer = udata.u_dptr;

    while (blocks != 0)
    {
        for (tries = 0; tries < 3; tries ++)
        {
            nudge_timer();
            if (tries != 0)
                fd_recalibrate();
            fd_seek(lba);

            fd765_sectors = 10 - fd765_sector;
            if (fd765_sectors > blocks)
                fd765_sectors = blocks;

            if (is_read)
                fd765_do_read();
            else
                fd765_do_write();

            /* Did it work ? */
            if ((fd765_status[0] & 0xc0) == 0)
                break;
        }
        if (tries == 3)
        {
            kprintf("fd%d: I/O error %d:%d\n", is_read, lba);
            udata.u_error = EIO;
            break;
        }
        lba += fd765_sectors;
        blocks -= fd765_sectors;
        ct += fd765_sectors;
    }

    return ct << BLKSHIFT;
}
コード例 #6
0
ファイル: devhd.c プロジェクト: EtchedPixels/FUZIX
static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
{
    uint16_t dptr, nb;
    irqflags_t irq;
    uint8_t err;

    if(rawflag == 1 && d_blkoff(9))
        return -1;

    hd_map = rawflag;

    dptr = (uint16_t)udata.u_dptr;
    nb = udata.u_nblock;
        
    while (udata.u_nblock--) {
        *disknum = minor;
        *diskcylh = udata.u_block >> 8;
        *diskcyll = udata.u_block;
        *diskcmd = 1;
        if ((err = *diskstat) != 0) {
            kprintf("hd%d: disk error %x\n", err);
            udata.u_error = EIO;
            return -1;
        }
        
        irq = di();
        if (is_read)
            hd_read_data(dptr);
        else
            hd_write_data(dptr);
        irqrestore(irq);
        udata.u_block++;
        dptr += 512;
    }
    return nb;
}
コード例 #7
0
ファイル: devsdc.c プロジェクト: EtchedPixels/FUZIX
/* blkdev method: transfer sectors */
static uint16_t sdc_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
{
       	uint8_t nb = 0;
	uint32_t lba;             /* holds 32 bit lsn */
	uint8_t *ptr = ((uint8_t *)&lba) + 1;      /* points to 24 bit lba in blk op */
	uint8_t t;                /* temporarory sdc status holder */
	uint8_t cmd;              /* holds SDC command value */
	sdc_transfer_function_t fptr;  /* holds which xfer routine we want */

	if (rawflag == 1 && d_blkoff(9))
		return -1;

	/* pass rawflag to assembler */
	sdcpage = rawflag;


	/* we get 256 bytes per lba in SDC so convert */
	udata.u_nblock *= 2;
	lba = udata.u_block * 2;
	ptr[0] |= (minor & 0x7f) << 1;

	/* setup cmd pointer and command value from blk_op */
	if (is_read) {
		cmd = 0x80;
		fptr = sdc_read_data;
	} else {
		cmd = 0xa0;
		fptr = sdc_write_data;
	}

	/* apply our drive value 0 or 1 */
	if (minor & 0x80)
		cmd++;

	while (udata.u_nblock--) {
		/* load up registers */
		sdc_reg_param1 = ptr[0];
		sdc_reg_param2 = ptr[1];
		sdc_reg_param3 = ptr[2];
		sdc_reg_cmd= cmd;
		asm("\texg x,x\n");     /* delay 16us minimum */
		asm("\texg x,x\n");
		/* wait till SDC is ready */
		do {
			t=sdc_reg_stat;
			if (t & SDC_FAIL)
				goto fail;
		} while(!(t & SDC_READY));
		/* do our low-level xfer function */
		fptr(udata.u_dptr);
		/* and wait will ready again, and test for failure */
		do {
			t=sdc_reg_stat;
			if( t & SDC_FAIL )
				goto fail;
		} while (t & SDC_BUSY);
		/* increment our blk_op values for next 256 bytes sector */
		udata.u_dptr += 256;
		lba++;
		nb++;
	}
	/*  Huzzah!  success! */
	return nb << 8;
	/* Boo!  failure */
 fail:	sdc_reg_ctl = 0x00;
	udata.u_error = EIO;
	return -1;
}
コード例 #8
0
ファイル: devfd.c プロジェクト: davidgiven/FUZIX
static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
{
    uint16_t nb = 0;
    int tries;
    uint8_t err = 0;
    uint8_t *driveptr = &fd_tab[minor & 1];
    irqflags_t irq;

    if(rawflag == 1 && d_blkoff(BLKSHIFT))
        return -1;

    udata.u_nblock *= 2;

    if (rawflag == 2)
        goto bad2;

    irq = di();
    if (fd_selected != minor) {
        uint8_t err = fd_motor_on(minor|(minor > 1 ? 0: 0x10));
        if (err)
            goto bad;
        motorct = 150;	/* 3 seconds */
    }
    irqrestore(irq);


//    kprintf("Issue command: %c drive %d block %d for %d\n", "wr"[is_read], minor, udata.u_block, udata.u_nblock);
    fd_cmd[0] = rawflag;
    fd_cmd[1] = is_read ? FD_READ : FD_WRITE;

    /* There are 16 256 byte sectors for DSDD. These are organised so that we
       switch head then step.

       Sectors 0-15 (our block 0-7)	Track 0, side 0
       Sectors 16-31 (our block 8-15)	Track 0, side 1

       etc */
    fd_cmd[2] = udata.u_block / 16;		/* Get the track we need */
    fd_cmd[3] = ((udata.u_block & 15) << 1);    /* 0 - 1 base is corrected in asm */
    fd_cmd[4] = is_read ? OPDIR_READ: OPDIR_WRITE;

    fd_data = (uint16_t)udata.u_dptr;

    while (udata.u_nblock--) {
        for (tries = 0; tries < 4 ; tries++) {
//            kprintf("Sector: %d Head: %d Track %d\n", (fd_cmd[3]&15)+1, fd_cmd[3]>>4, fd_cmd[2]);
            err = fd_operation(driveptr);
            if (err == 0)
                break;
            if (tries > 1)
                fd_reset(driveptr);
        }
        /* FIXME: should we try the other half and then bale out ? */
        if (tries == 3)
            goto bad;
        fd_data += 256;
        fd_cmd[3]++;	/* Next sector for next block */
        if (fd_cmd[3] == 32) {	/* Next track */
            fd_cmd[3] = 0;
            fd_cmd[2]++;
        }
        nb++;
    }
    return nb << (BLKSHIFT - 1);
bad:
    kprintf("fd%d: error %x\n", minor, err);
bad2:
    udata.u_error = EIO;
    return -1;
}
コード例 #9
0
ファイル: devfd.c プロジェクト: davidgiven/FUZIX
static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
{
    int8_t tries;
    uint8_t err = 0;
    uint8_t drive = minor & 3;
    uint8_t trackno, sector;
    uint8_t large = !(minor & 0x10);
    const uint8_t *skew = skewtab[large];		/* skew table */

    if(rawflag == 2)
        goto bad2;

    fd_map = rawflag;
    if (rawflag && d_blkoff(BLKSHIFT))
            return -1;


    /* Command to go to the controller after any seek is done */
    fd_cmd[0] = is_read ? FD_READ : FD_WRITE;
    /* Control byte: autowait, DD, motor, 5", drive bit */
    fd_cmd[1] = 0xE0 | selmap[drive];
    if (large)
        fd_cmd[1] = 0x10;	/* turn on 8" bit */
    /* Directon of xfer */
    fd_cmd[2] = is_read ? OPDIR_READ: OPDIR_WRITE;
    fd_cmd[5] = 0x10 | delay[drive];

    /*
     *	Restore the track register to match this drive
     */
    if (track[drive] != 0xFF)
        fd_track = track[drive];
    else
        fd_reset();

    /*
     *	Begin transfers
     */
    while (udata.u_done < udata.u_nblock) {
        /* Need to consider SS v DS here */
        if (large) {
            fd_aux = 0x4C | (udata.u_block & 16) ? 2 : 0;
            trackno = udata.u_block / 32;
            sector = udata.u_block % 16;
        } else {
            trackno = udata.u_block / 20;
            sector = udata.u_block % 20;
            if (sector > 9) {
                sector -= 10;
                fd_aux = 0x5E;	/* side 1 */
            } else
                fd_aux = 0x5C;
        }
        /* Buffer */
        fd_cmd[3] = ((uint16_t)udata.u_dptr) & 0xFF;
        fd_cmd[4] = ((uint16_t)udata.u_dptr) >> 8;

        for (tries = 0; tries < 4 ; tries++) {
            (void)fd_data;
            fd_sector = skew[sector];	/* Also makes 1 based */
            if (fd_track != trackno) {
                fd_data = trackno;
                if (fd_seek()) {
                    fd_reset();
                    continue;
                }
            }
            /* Do the read or write */
            err = fd_operation();
            if (err == 0)
                break;
            /* Try and recover */
            if (tries > 1)
                fd_reset();
        }
        if (tries == 4)
            goto bad;
        udata.u_block++;
        udata.u_done++;
    }
    /* Save the track */
    track[drive] = fd_track;
    return udata.u_done << 9;
bad:
    track[drive] = fd_track;
    kprintf("fd%d: error %x\n", minor, err);
bad2:
    udata.u_error = EIO;
    return -1;
}