USG_PG3/usr/source/io2/rh.c
#
/*
*/
#include "../head/param.h"
#include "../head/buf.h"
#include "../head/bufx.h"
#include "../head/conf.h"
#include "../head/systm.h"
#include "../head/user.h"
#include "../head/userx.h"
#include "../head/proc.h"
#include "../head/procx.h"
#include "../head/seg.h"
/*
* startup routine for RH controllers.
*/
#define IENABLE 0100
#define RHWCOM 060
#define RHRCOM 070
#define GO 01
rhstart(bp, devloc, devblk, abae)
struct buf *bp;
int *devloc, *abae;
{
register int *dp;
register struct buf *rbp;
register int com;
dp = devloc;
rbp = bp;
if(cputype == 70)
*abae = rbp->b_xmem;
*dp = devblk; /* block address */
*--dp = rbp->b_addr; /* buffer address */
*--dp = rbp->b_wcount; /* word count */
com = IENABLE | GO |
((rbp->b_xmem & 03) << 8);
if (rbp->b_flags&B_READ) /* command + x-mem */
com =| RHRCOM; else
com =| RHWCOM;
*--dp = com;
}
/*
* 11/70 routine to allocate the
* UNIBUS map and initialize for
* a unibus device.
* The code here and in
* rhstart assumes that an rh on an 11/70
* is an rh70 and contains 22 bit addressing.
*/
int mapwant;
mapalloc(abp)
struct buf *abp;
{
register i, j;
register struct buf *bp;
long dble;
int regno;
bp = abp;
if(cputype != 70 || bp->b_wcount == 0)
return;
j = (-bp->b_wcount-1)/4096+1;
spl6();
while((regno = malloc(ubmap, j)) == 0) {
mapwant++;
sleep(ubmap, PSWP);
}
spl0();
dble.loword = bp->b_addr;
dble.hiword = bp->b_xmem;
j = 2*(regno+j);
for(i = regno*2; i<j ; i =+ 2) {
UBMAP->r[i] = dble.loword;
UBMAP->r[i+1] = dble.hiword;
dble =+ 8192;
}
bp->b_xmem = regno>>3;
bp->b_addr = regno<<13;
bp->b_flags =| B_MAP;
}
mapfree(abp)
struct buf *abp;
{
register struct buf *bp;
register regno;
bp = abp;
bp->b_flags =& ~B_MAP;
regno = bp->b_xmem<<3 | ((bp->b_addr>>13)&07);
mfree(ubmap, (-bp->b_wcount-1)/4096+1, regno);
if(mapwant) {
wakeup(ubmap);
mapwant = 0;
}
}
/*
* For inverted disk areas, negcyl cchecks physical I/O
* requests to see if they cross cylinder boundaries and
* breaks the request into two parts if needed
*/
/*
* NOTE: THE SWAP AREA MAY NOT BE ON AN INVERTED DISK AREA
*/
negcyl(strat,bp,dev,flag,nblks,nsect)
struct buf *bp;
int (*strat)();
{
register char *bend,*beg;
register char *count;
char *savcnt;
count = u.u_count;
beg = lshift(u.u_offset,-9);
bend = beg + ((count>>9)&0177) - ((count&0777)?0:1);
if((bend > beg)&&(ldiv(bend,nsect)!=ldiv(beg,nsect))){
savcnt = u.u_count = (nsect - lrem(beg,nsect))*512;
physio(strat,bp,dev,flag,nblks);
if(u.u_error)
return;
if(u.u_count){
u.u_count =+ count - savcnt;
return(1);
}
dpadd(u.u_offset,savcnt);
u.u_count = count - savcnt;
u.u_base =+ savcnt;
}
return(0);
}