/* * Sony driver * * (C) 1984 UniSoft Corp. of Berkeley CA * * UniPlus Source Code. This program is proprietary * with Unisoft Corporation and is not to be reproduced * or used in any manner except as authorized in * writing by Unisoft. */#include "sys/param.h"#include "sys/mmu.h"#include "sys/types.h"#include "sys/inode.h"#include "sys/ino.h"#include "saio.h"#include "sys/pport.h"#include "sys/sony.h"#include "sys/cops.h"char initflg;snopen(ip)register struct iob *ip;{	register unit = ip->i_unit;	if (unit >= NSN) {		printf("Invalid device 0x%x\n", unit);		return(-1);	}	if (initflg == 0) {		if (sninit() < 0)			return(-1);		initflg++;	}	if (snwaitrdy()) {		printf("snopen: wait to check disk insertion failed\n");		return(-1);	}	if (SNIOB->diskin != 0xff) {		printf("snopen: no diskette inserted\n");		return(-1);	}	return(0);}sninit(){	char c = 0x00;			/* to avoid clear byte intstructions */	register i;	if(!SNIOB->type) {		printf("sninit: not a sony drive\n");		return(-1);	}	SNIOB->drive=0x80;		/* always lower drive */	SNIOB->side = c;		/* always first side */	SNIOB->mask= 0xff;		/* clear ints and enable */	if(snwaitrdy()) {		printf("sninit: wait to check drive connected failed\n");		return(-1);	}	if((i=SNIOB->drv_connect) != 0xff) {		printf("sninit: no drive connected (0x%x)\n", i);		return(-1);	}	if(snwaitrdy()) {		printf("sninit: wait to clear status failed\n");		return(-1);	}	SNIOB->gobyte=SN_CLRST;	if(snwaitrdy()) {		printf("sninit: command to clear status failed\n");		return(-1);	}	SNIOB->mask =0x80;		/* enable interrupts */	if(snwaitrdy()) {		printf("sninit: wait to enable interrupts failed\n");		return(-1);	}	SNIOB->gobyte=SN_STMASK;	return(0);}snstrategy(ip, func)register struct iob *ip;{	register unit = ip->i_unit;	register daddr_t bn;	register resid;	int offset;	caddr_t addr;	if (unit >= NSN)		return(-1);	if (ip->i_bn < 0) {		printf("snstrategy: bn < 0\n");		return(-1);	}	resid = ip->i_cc;loop:	if (resid < PBSIZE)		goto out;	offset = ip->i_cc - resid;	addr = ip->i_ma + offset;	bn = ip->i_bn + (offset >> PBSHIFT);	if (bn >= SN_MAXBN)		goto out;	if ((bn == 0) && (ip->i_bblk == BOOTDISK))		func |= F_BOOT;	if (snrw(unit, bn, func, addr) != 0)		return(-1);	resid -= PBSIZE;	goto loop;out:	if (resid != 0)		printf("snstrategy: bn=%d resid=%d\n", ip->i_bn, resid);	return(ip->i_cc - resid);}struct sn_blockmap {	int maxblock, sectors;} sn_blockmap[] = {		192, 12,		176, 11,		160, 10,		144, 9,		128, 8 };/* ARGSUSED */snrw(unit, bn, rw, addr)int unit, rw;register daddr_t bn;register caddr_t addr;{	register char *pm;	register struct sn_blockmap *p = sn_blockmap;	register short i;	int track, sector;	char c = 0x00;	struct sn_hdr sn_hdr;	register caddr_t haddr;	register orig_bn;#ifdef DEBUGchar getsbuf[10];#endif DEBUG	orig_bn = bn;	if(snwaitrdy())		return(-1);	SNIOB->side=c;	SNIOB->drive=0x80;	track = 0;	while( bn >= p->maxblock ) {		bn -= p->maxblock;		track += 16;		p++;	}	sector = bn % p->sectors;	track += bn / p->sectors;	SNIOB->track = track; 	SNIOB->sector= sector;	if ((rw&~F_BOOT) == READ) {#ifdef DEBUGprintf("r%d ", orig_bn);#endif DEBUG		SNIOB->cmd=SN_READ;	} else {#ifdef DEBUGprintf("w%d ", orig_bn);if ((sector==0) && (track==0))printf("writing actual block 0\n");#endif DEBUG		SNIOB->cmd=SN_WRITE;		if (orig_bn == 0) {			if (rw & F_BOOT)				sn_hdr.fileid = FILEID;			else				sn_hdr.fileid = 0;#ifdef DEBUGprintf("snrw: file id = 0x%x\n", sn_hdr.fileid);printf("sector=%d, track=%d\n", sector, track);gets(getsbuf);#endif DEBUG			sn_hdr.version = 0;			sn_hdr.volume = 0;			sn_hdr.relpg = 0;			sn_hdr.dum1 = 0;			sn_hdr.dum2 = 0;			i = sizeof(sn_hdr) - 1;			pm = (char *)SN_HDRBUF;	/* write special 12-byte hdr */			haddr = (char *)&sn_hdr;			do {				*pm++;		/* cmos ram, every other byte */				*pm++ = *haddr++;			} while (--i != -1);		}		i = 511;		pm = (char *)SN_DATABUF;	/* write reg 512-byte buffer */		do {			*pm++;			/* cmos ram, every other byte */			*pm++ = *addr++;		} while (--i != -1);	}	SNIOB->gobyte = SN_CMD;	while ((COPSADDR->e_irb & FDIR) == 0)	;	if( i = SNIOB->status) {		printf("SNIOB->status = 0x%x\n",i);		return(-1);	}	if ((rw&~F_BOOT) == READ) {#ifdef DEBUGif ((sector==0) && (track==0))printf("actual block 0 read in\n");#endif DEBUG		i = 511;		pm = (char *)SN_DATABUF;	/* write reg 512-byte buffer */		do {			*pm++;			/* cmos ram, every other byte */			*addr++ = *pm++;#ifdef DEBUGif ((sector==0) && (track==0))printf("0x%x ", *(addr-1));#endif DEBUG		} while (--i != -1);	}	SNIOB->mask = SN_CLEARMSK;	SNIOB->gobyte = SN_CLRST;	return (0);}snwaitrdy(){	register int i, j, k;	/* Don't give up - may take a while before disk insertion check	 * (in open) can be made.	 */	k = 0xC0000;	do {		i = 1000;		while (((PPADDR)->d_irb & DSKDIAG) == 0) {	/* busy */			for(j=0;j<1024;j++);		/* don't access flpy */			if (--i < 0) {				printf("snwaitrdy: DSKDIAG not ready\n");				return(1);			}		}		if (SNIOB->gobyte == 0)			return(0);	} while (--k);	printf("snwaitrdy: drive not ready\n");	return (1);}sneject(ip)register struct iob *ip;{	register unit = ip->i_unit;	register short i;	if (unit >= NSN) {		printf("Invalid device 0x%x\n", unit);		return(-1);	}	if (initflg == 0) {		if (sninit() < 0)			return(-1);		initflg++;	}	if (snwaitrdy()) {		printf("sneject: wait to check disk insertion failed\n");		return(-1);	}	if (SNIOB->diskin != 0xff) {		printf("sneject: no diskette inserted\n");		return(-1);	}	SNIOB->cmd=SN_EJECT;	SNIOB->gobyte = SN_CMD;	while ((COPSADDR->e_irb & FDIR) == 0)	;	if( i = SNIOB->status) {		printf("SNIOB->status = 0x%x\n",i);		return(-1);	}	SNIOB->mask = SN_CLEARMSK;	SNIOB->gobyte = SN_CLRST;	return (0);}eject(unit)register unit;{	struct iob ioblk;	ioblk.i_unit = unit;	if (sneject(&ioblk))		return(-1);	return(0);}