?? flp.c
字號:
#ifndef lintstatic char *sccsid = "@(#)flp.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1989 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification history: /sys/vax/flp.c * * 30-May-89 darrell * Added include of ../../machine/common/cpuconf.h -- cpu types * were moved there. * ***********************************************************************/#if VAX780#include "../h/param.h"#include "../h/systm.h"#include "../h/conf.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/uio.h"#include "../vax/cons.h"#include "../vax/cpu.h"#include "../../machine/common/cpuconf.h"#include "../vax/flp.h"#include "../vax/mtpr.h"struct { short fl_state; /* open and busy flags */ short fl_active; /* driver state flag */ struct buf *fl_buf; /* buffer we're using */ unsigned char *fl_xaddr; /* transfer address */ short fl_errcnt;} fltab;/*ARGSUSED*/flopen(dev, flag) dev_t dev; int flag;{ struct buf *geteblk();#if VAX750 if (cpu != VAX_780) return (ENXIO);#endif if (fltab.fl_state != 0) return (ENXIO); fltab.fl_state = FL_OPEN; fltab.fl_buf = geteblk(512); fltab.fl_active = FL_IDLE; return (0);}/*ARGSUSED*/flclose(dev, flag) dev_t dev; int flag;{ brelse(fltab.fl_buf); fltab.fl_state = 0;}floperation(rw, uio) enum uio_rw rw; struct uio *uio;{ register struct buf *bp; register int i; int error; /* * Assume one block read/written for each call - * and enforce this by checking for block size of 128. * Use the b_blkno field to address * physical, 128-byte blocks (u.u_offset/128). * This is checked for validity, and is further interpreted as: * * track# * (sectors/track) + sector # */ if (uio->uio_resid == 0) return (0); (void) spl4(); while (fltab.fl_state & FL_BUSY) sleep((caddr_t)&fltab, PRIBIO); fltab.fl_state |= FL_BUSY; (void) spl0(); bp = fltab.fl_buf; error = 0; while ((i = imin(RXBYSEC, uio->uio_resid)) > 0) { bp->b_blkno = uio->uio_offset>>7; if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0177) != 0) return (ENXIO); if (rw == UIO_WRITE) { error = uiomove(bp->b_un.b_addr, i, UIO_WRITE, uio); if (error) break; } bp->b_flags = rw == UIO_WRITE ? B_WRITE : B_READ; (void) spl4(); flstart(); while ((bp->b_flags & B_DONE) == 0) sleep((caddr_t)bp, PRIBIO); (void) spl0(); if (bp->b_flags & B_ERROR) { error = EIO; break; } if (rw == UIO_READ) { error = uiomove(bp->b_un.b_addr, i, UIO_READ, uio); if (error) break; } } fltab.fl_state &= ~FL_BUSY; wakeup((caddr_t)&fltab); return (error);}/*ARGSUSED*/flread(dev, uio) dev_t dev; struct uio *uio;{ return (floperation(UIO_READ, uio));}/*ARGSUSED*/flwrite(dev, uio) dev_t dev; struct uio *uio;{ return (floperation(UIO_WRITE, uio));}flstart(){ register struct buf *bp; bp = fltab.fl_buf; fltab.fl_active = FL_MAND; fltab.fl_errcnt = 0; fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr; bp->b_resid = 0; bp->b_bcount = RXBYSEC; /* always transfer a full sector */ if ((mfpr(TXCS) & TXCS_RDY) == 0) /* not ready to receive order */ return; /* * Wake up floppy LSI software with command */ fltab.fl_active = FL_SEC; if ((bp->b_flags&B_READ) == B_READ) mtpr(TXDB, FL_RS); else mtpr(TXDB, FL_WS);}/* * See if we want to transmit something * to the floppy - and do it */conxfl(){ register int databyte; register struct buf *bp; bp = fltab.fl_buf; switch (fltab.fl_active) { case FL_MAND: /* send command */ if ((bp->b_flags&B_READ) == B_READ) mtpr(TXDB,FL_RS); else mtpr(TXDB, FL_WS); fltab.fl_active = FL_SEC; break; case FL_SEC: /* send sector address */ databyte = (int)bp->b_blkno % RXSTRK + 1; mtpr(TXDB, FL_DATA | databyte); fltab.fl_active = FL_TRACK; break; case FL_TRACK: /* send track address */ databyte = (int)bp->b_blkno / RXSTRK; mtpr(TXDB , FL_DATA | databyte); if ((bp->b_flags&B_READ) == B_READ) /* prepare to receive complete */ fltab.fl_active = FL_COM; else /* prepare to send data */ fltab.fl_active = FL_DAX; break; case FL_DAX: databyte = *(fltab.fl_xaddr++); mtpr(TXDB, FL_DATA | databyte); if (--bp->b_bcount == 0) fltab.fl_active = FL_COM; break; case FL_CAN: /* give cancel order */ mtpr(TXDB, FL_CANCEL); if (++fltab.fl_errcnt <= FLERRS) { /* If error count permits, retry order */ fltab.fl_active = FL_MAND; bp->b_bcount = RXBYSEC; fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr; } else { /* * We're really stupid today - call it an * error and give up */ bp->b_flags |= B_ERROR | B_DONE; bp->b_resid = -RXBYSEC; fltab.fl_active = FL_IDLE; wakeup((caddr_t)bp); } }}cnrfl(c) int c;{ register int datum; register struct buf *bp; datum = c; bp = fltab.fl_buf; if (datum == FL_PERR) { /* * Got a protocol error - cancel the * current function and try again if error count isn't * too great. First, though, make sure that an actual * transaction is in progress (so a spurious error from * the LSI won't screw us up too much! */ if (fltab.fl_active != FL_IDLE) fltab.fl_active = FL_CAN; } else switch(fltab.fl_active ) { case FL_DAR: /* expecting a datum */ if ((c&RXDB_ID) != FL_DATA) goto error; *(fltab.fl_xaddr++) = (c & RXDB_DATA); if (--bp->b_bcount==0) { fltab.fl_active = FL_IDLE; bp->b_flags |= B_DONE; wakeup((caddr_t)bp); } break; case FL_COM: /* expecting a "function complete" */ if ((c&RXDB_ID)!= FL_FFC || (c&FL_ERR) == FL_ERR){error: bp->b_flags |= B_ERROR | B_DONE; bp->b_resid = -bp->b_bcount; fltab.fl_active = FL_IDLE; wakeup((caddr_t)bp); } else if ((bp->b_flags&B_READ) == B_READ) /* got function complete, now get data */ fltab.fl_active = FL_DAR; else { /* got function complete on write - finish up */ fltab.fl_active = FL_IDLE; bp->b_flags |= B_DONE; wakeup((caddr_t)bp); } break; }}#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -