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 */
if (fltab
.fl_state
!= 0) {
fltab
.fl_state
= FL_OPEN
;
fltab
.fl_buf
= geteblk();
fltab
.fl_active
= FL_IDLE
;
* 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 #
while (fltab
.fl_state
& FL_BUSY
)
sleep((caddr_t
)&fltab
, PRIBIO
);
fltab
.fl_state
|= FL_BUSY
;
while ((i
= min(RXBYSEC
, u
.u_count
)) != 0) {
bp
->b_blkno
= u
.u_offset
>>7;
if (bp
->b_blkno
>= MAXSEC
|| (u
.u_offset
& 0177) != 0) {
/* block number out of range */
/* or offset in middle of block */
iomove(bp
->b_un
.b_addr
, i
, B_WRITE
);
while ((bp
->b_flags
& B_DONE
) == 0)
sleep((caddr_t
)bp
, PRIBIO
);
if (bp
->b_flags
& B_ERROR
) {
iomove(bp
->b_un
.b_addr
, i
, B_READ
);
fltab
.fl_state
&= ~FL_BUSY
;
fltab
.fl_active
= FL_MAND
;
fltab
.fl_xaddr
= (unsigned char *) bp
->b_un
.b_addr
;
bp
->b_bcount
= RXBYSEC
; /* always transfer a full sector */
if ((mfpr(TXCS
) & TXCS_RDY
) == 0)
/* not ready to receive order */
* Wake up floppy LSI software with command
fltab
.fl_active
= FL_SEC
;
if ((bp
->b_flags
&B_READ
) == B_READ
)
* See if we want to transmit something
* to the floppy - and do it
switch (fltab
.fl_active
) {
case FL_MAND
: /* send command */
if ((bp
->b_flags
&B_READ
) == B_READ
)
fltab
.fl_active
= FL_SEC
;
case FL_SEC
: /* send sector address */
databyte
= (int)bp
->b_blkno
% RXSTRK
+ 1;
mtpr(TXDB
, FL_DATA
| databyte
);
fltab
.fl_active
= FL_TRACK
;
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
;
/* prepare to send data */
fltab
.fl_active
= FL_DAX
;
databyte
= *(fltab
.fl_xaddr
++);
mtpr(TXDB
, FL_DATA
| databyte
);
fltab
.fl_active
= FL_COM
;
case FL_CAN
: /* give cancel order */
if (++fltab
.fl_errcnt
<= FLERRS
) {
/* If error count permits, retry order */
fltab
.fl_active
= FL_MAND
;
fltab
.fl_xaddr
= (unsigned char *) bp
->b_un
.b_addr
;
* We're really stupid today - call it an
bp
->b_flags
|= B_ERROR
| B_DONE
;
fltab
.fl_active
= FL_IDLE
;
* 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
)
*(fltab
.fl_xaddr
++) = (c
& RXDB_DATA
);
fltab
.fl_active
= FL_IDLE
;
case FL_COM
: /* expecting a "function complete" */
if ((c
&RXDB_ID
)!= FL_FFC
|| (c
&FL_ERR
) == FL_ERR
){
bp
->b_flags
|= B_ERROR
| B_DONE
;
bp
->b_resid
= -bp
->b_bcount
;
fltab
.fl_active
= FL_IDLE
;
} else if ((bp
->b_flags
&B_READ
) == B_READ
)
/* got function complete, now get data */
fltab
.fl_active
= FL_DAR
;
/* got function complete on write - finish up */
fltab
.fl_active
= FL_IDLE
;