1*41480Smckusick /* 2*41480Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 3*41480Smckusick * All rights reserved. 4*41480Smckusick * 5*41480Smckusick * %sccs.include.redist.c% 6*41480Smckusick * 7*41480Smckusick * @(#)dma.c 7.1 (Berkeley) 05/08/90 8*41480Smckusick */ 9*41480Smckusick 10*41480Smckusick /* 11*41480Smckusick * DMA driver 12*41480Smckusick */ 13*41480Smckusick 14*41480Smckusick #include "param.h" 15*41480Smckusick #include "systm.h" 16*41480Smckusick #include "time.h" 17*41480Smckusick #include "kernel.h" 18*41480Smckusick #include "proc.h" 19*41480Smckusick #include "dmareg.h" 20*41480Smckusick #include "dmavar.h" 21*41480Smckusick #include "device.h" 22*41480Smckusick 23*41480Smckusick #include "machine/cpu.h" 24*41480Smckusick #include "machine/isr.h" 25*41480Smckusick 26*41480Smckusick extern void isrlink(); 27*41480Smckusick extern void printf(); 28*41480Smckusick extern void panic(); 29*41480Smckusick extern void _insque(); 30*41480Smckusick extern void _remque(); 31*41480Smckusick extern void timeout(); 32*41480Smckusick extern int splbio(); 33*41480Smckusick extern void splx(); 34*41480Smckusick extern u_int kvtop(); 35*41480Smckusick extern void PCIA(); 36*41480Smckusick 37*41480Smckusick /* 38*41480Smckusick * The largest single request will be MAXPHYS bytes which will require 39*41480Smckusick * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of 40*41480Smckusick * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the 41*41480Smckusick * buffer is not page aligned (+1). 42*41480Smckusick */ 43*41480Smckusick #define DMAMAXIO (MAXPHYS/NBPG+1) 44*41480Smckusick 45*41480Smckusick #define DMATIMO 15 46*41480Smckusick 47*41480Smckusick struct dma_softc { 48*41480Smckusick struct dmadevice *sc_hwaddr; 49*41480Smckusick struct dmaBdevice *sc_Bhwaddr; 50*41480Smckusick int sc_type; 51*41480Smckusick int sc_cur; 52*41480Smckusick int sc_cmd; 53*41480Smckusick int sc_timo; 54*41480Smckusick int sc_count[DMAMAXIO+1]; 55*41480Smckusick char *sc_addr[DMAMAXIO+1]; 56*41480Smckusick } dma_softc[NDMA]; 57*41480Smckusick 58*41480Smckusick /* types */ 59*41480Smckusick #define DMA_B 0 60*41480Smckusick #define DMA_C 1 61*41480Smckusick 62*41480Smckusick struct devqueue dmachan[NDMA + 1]; 63*41480Smckusick int dmaintr(); 64*41480Smckusick void dmatimo(); 65*41480Smckusick 66*41480Smckusick #ifdef DEBUG 67*41480Smckusick int dmadebug = 0; 68*41480Smckusick #define DDB_WORD 0x01 /* same as DMAGO_WORD */ 69*41480Smckusick #define DDB_LWORD 0x02 /* same as DMAGO_LWORD */ 70*41480Smckusick #define DDB_FOLLOW 0x04 71*41480Smckusick #define DDB_IO 0x08 72*41480Smckusick 73*41480Smckusick long dmahits[NDMA]; 74*41480Smckusick long dmamisses[NDMA]; 75*41480Smckusick long dmabyte[NDMA]; 76*41480Smckusick long dmaword[NDMA]; 77*41480Smckusick long dmalword[NDMA]; 78*41480Smckusick #endif 79*41480Smckusick 80*41480Smckusick void 81*41480Smckusick dmainit() 82*41480Smckusick { 83*41480Smckusick register struct dmareg *dma = (struct dmareg *)DMA_BASE; 84*41480Smckusick register struct dma_softc *dc; 85*41480Smckusick register int i; 86*41480Smckusick char rev; 87*41480Smckusick 88*41480Smckusick /* 89*41480Smckusick * Determine the DMA type. 90*41480Smckusick * Don't know how to easily differentiate the A and B cards, 91*41480Smckusick * so we just hope nobody has an A card (A cards will work if 92*41480Smckusick * DMAINTLVL is set to 3). 93*41480Smckusick */ 94*41480Smckusick if (!badbaddr((char *)&dma->dma_id[2])) 95*41480Smckusick rev = dma->dma_id[2]; 96*41480Smckusick else { 97*41480Smckusick rev = 'B'; 98*41480Smckusick #if !defined(HP320) 99*41480Smckusick panic("dmainit: DMA card requires hp320 support"); 100*41480Smckusick #endif 101*41480Smckusick } 102*41480Smckusick 103*41480Smckusick dc = &dma_softc[0]; 104*41480Smckusick for (i = 0; i < NDMA; i++) { 105*41480Smckusick dc->sc_hwaddr = (i & 1) ? &dma->dma_chan1 : &dma->dma_chan0; 106*41480Smckusick dc->sc_Bhwaddr = (i & 1) ? &dma->dma_Bchan1 : &dma->dma_Bchan0; 107*41480Smckusick dc->sc_type = rev == 'B' ? DMA_B : DMA_C; 108*41480Smckusick dc++; 109*41480Smckusick dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; 110*41480Smckusick } 111*41480Smckusick dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; 112*41480Smckusick timeout(dmatimo, (caddr_t)0, DMATIMO * hz); 113*41480Smckusick 114*41480Smckusick printf("dma: 98620%c with 2 channels, %d bit DMA\n", 115*41480Smckusick rev, rev == 'B' ? 16 : 32); 116*41480Smckusick } 117*41480Smckusick 118*41480Smckusick int 119*41480Smckusick dmareq(dq) 120*41480Smckusick register struct devqueue *dq; 121*41480Smckusick { 122*41480Smckusick register int i; 123*41480Smckusick register int chan; 124*41480Smckusick register int s = splbio(); 125*41480Smckusick 126*41480Smckusick chan = dq->dq_ctlr; 127*41480Smckusick i = NDMA; 128*41480Smckusick while (--i >= 0) { 129*41480Smckusick if ((chan & (1 << i)) == 0) 130*41480Smckusick continue; 131*41480Smckusick if (dmachan[i].dq_forw != &dmachan[i]) 132*41480Smckusick continue; 133*41480Smckusick insque(dq, &dmachan[i]); 134*41480Smckusick dq->dq_ctlr = i; 135*41480Smckusick splx(s); 136*41480Smckusick return(1); 137*41480Smckusick } 138*41480Smckusick insque(dq, dmachan[NDMA].dq_back); 139*41480Smckusick splx(s); 140*41480Smckusick return(0); 141*41480Smckusick } 142*41480Smckusick 143*41480Smckusick void 144*41480Smckusick dmafree(dq) 145*41480Smckusick register struct devqueue *dq; 146*41480Smckusick { 147*41480Smckusick int unit = dq->dq_ctlr; 148*41480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 149*41480Smckusick register struct devqueue *dn; 150*41480Smckusick register int chan, s; 151*41480Smckusick 152*41480Smckusick s = splbio(); 153*41480Smckusick dc->sc_timo = 0; 154*41480Smckusick DMA_CLEAR(dc); 155*41480Smckusick remque(dq); 156*41480Smckusick chan = 1 << unit; 157*41480Smckusick for (dn = dmachan[NDMA].dq_forw; 158*41480Smckusick dn != &dmachan[NDMA]; dn = dn->dq_forw) { 159*41480Smckusick if (dn->dq_ctlr & chan) { 160*41480Smckusick remque((caddr_t)dn); 161*41480Smckusick insque((caddr_t)dn, (caddr_t)dq->dq_back); 162*41480Smckusick splx(s); 163*41480Smckusick dn->dq_ctlr = dq->dq_ctlr; 164*41480Smckusick (dn->dq_driver->d_start)(dn->dq_unit); 165*41480Smckusick return; 166*41480Smckusick } 167*41480Smckusick } 168*41480Smckusick splx(s); 169*41480Smckusick } 170*41480Smckusick 171*41480Smckusick void 172*41480Smckusick dmago(unit, addr, count, flags) 173*41480Smckusick int unit; 174*41480Smckusick register char *addr; 175*41480Smckusick register int count; 176*41480Smckusick register int flags; 177*41480Smckusick { 178*41480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 179*41480Smckusick register char *dmaend = NULL; 180*41480Smckusick register int tcount, i; 181*41480Smckusick 182*41480Smckusick #ifdef DEBUG 183*41480Smckusick if (dmadebug & DDB_FOLLOW) 184*41480Smckusick printf("dmago(%d, %x, %x, %x)\n", 185*41480Smckusick unit, addr, count, flags); 186*41480Smckusick if (flags & DMAGO_LWORD) 187*41480Smckusick dmalword[unit]++; 188*41480Smckusick else if (flags & DMAGO_WORD) 189*41480Smckusick dmaword[unit]++; 190*41480Smckusick else 191*41480Smckusick dmabyte[unit]++; 192*41480Smckusick #endif 193*41480Smckusick #if defined(HP320) 194*41480Smckusick if (dc->sc_type == DMA_B && (flags & DMAGO_LWORD)) 195*41480Smckusick panic("dmago: no can do 32-bit DMA"); 196*41480Smckusick #endif 197*41480Smckusick /* 198*41480Smckusick * Build the DMA chain 199*41480Smckusick */ 200*41480Smckusick for (i = 0; i < DMAMAXIO && count; i++) { 201*41480Smckusick dc->sc_addr[i] = (char *)kvtop(addr); 202*41480Smckusick tcount = dc->sc_count[i] = 203*41480Smckusick MIN(count, NBPG - ((int)addr & PGOFSET)); 204*41480Smckusick addr += dc->sc_count[i]; 205*41480Smckusick count -= tcount; 206*41480Smckusick if (flags & (DMAGO_WORD|DMAGO_LWORD)) 207*41480Smckusick tcount >>= (flags & DMAGO_WORD) ? 1 : 2; 208*41480Smckusick if (dc->sc_addr[i] == dmaend 209*41480Smckusick #if defined(HP320) 210*41480Smckusick /* only 16-bit count on 98620B */ 211*41480Smckusick && (dc->sc_type != DMA_B || 212*41480Smckusick dc->sc_count[i-1] + tcount <= 65536) 213*41480Smckusick #endif 214*41480Smckusick ) { 215*41480Smckusick #ifdef DEBUG 216*41480Smckusick dmahits[unit]++; 217*41480Smckusick #endif 218*41480Smckusick dmaend += dc->sc_count[i]; 219*41480Smckusick dc->sc_count[i-1] += tcount; 220*41480Smckusick i--; 221*41480Smckusick } else { 222*41480Smckusick #ifdef DEBUG 223*41480Smckusick dmamisses[unit]++; 224*41480Smckusick #endif 225*41480Smckusick dmaend = dc->sc_addr[i] + dc->sc_count[i]; 226*41480Smckusick dc->sc_count[i] = tcount; 227*41480Smckusick } 228*41480Smckusick } 229*41480Smckusick if (count) 230*41480Smckusick panic("dmago maxphys"); 231*41480Smckusick dc->sc_count[i] = 0; 232*41480Smckusick dc->sc_cur = 0; 233*41480Smckusick /* 234*41480Smckusick * Set up the command word based on flags 235*41480Smckusick */ 236*41480Smckusick dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START; 237*41480Smckusick if ((flags & DMAGO_READ) == 0) 238*41480Smckusick dc->sc_cmd |= DMA_WRT; 239*41480Smckusick if (flags & DMAGO_LWORD) 240*41480Smckusick dc->sc_cmd |= DMA_LWORD; 241*41480Smckusick else if (flags & DMAGO_WORD) 242*41480Smckusick dc->sc_cmd |= DMA_WORD; 243*41480Smckusick if (flags & DMAGO_PRI) 244*41480Smckusick dc->sc_cmd |= DMA_PRI; 245*41480Smckusick 246*41480Smckusick /* 247*41480Smckusick * We should be able to skip the dma completion interrupt 248*41480Smckusick * if we only have one segment in the chain since many 249*41480Smckusick * devices generate their own completion interrupt. 250*41480Smckusick * However, on a 370 we have to take the interrupt on 251*41480Smckusick * read transfers to invalidate the external cache. 252*41480Smckusick */ 253*41480Smckusick if ((flags & DMAGO_NOINT) && i == 1 254*41480Smckusick #if defined(HP370) 255*41480Smckusick && ((flags & DMAGO_READ) == 0 || ectype != EC_PHYS) 256*41480Smckusick #endif 257*41480Smckusick ) 258*41480Smckusick dc->sc_cmd &= ~DMA_ENAB; 259*41480Smckusick #ifdef DEBUG 260*41480Smckusick #if defined(HP320) 261*41480Smckusick /* would this hurt? */ 262*41480Smckusick if (dc->sc_type == DMA_B) 263*41480Smckusick dc->sc_cmd &= ~DMA_START; 264*41480Smckusick #endif 265*41480Smckusick if (dmadebug & DDB_IO) 266*41480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 267*41480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) { 268*41480Smckusick printf("dmago: cmd %x\n", dc->sc_cmd); 269*41480Smckusick for (i = 0; dc->sc_count[i]; i++) 270*41480Smckusick printf(" %d: %d@%x\n", 271*41480Smckusick i, dc->sc_count[i], dc->sc_addr[i]); 272*41480Smckusick } 273*41480Smckusick #endif 274*41480Smckusick 275*41480Smckusick /* 276*41480Smckusick * Load and arm the channel 277*41480Smckusick */ 278*41480Smckusick dc->sc_timo = 1; 279*41480Smckusick DMA_ARM(dc, 0); 280*41480Smckusick } 281*41480Smckusick 282*41480Smckusick void 283*41480Smckusick dmastop(unit) 284*41480Smckusick register int unit; 285*41480Smckusick { 286*41480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 287*41480Smckusick register struct devqueue *dq; 288*41480Smckusick 289*41480Smckusick #ifdef DEBUG 290*41480Smckusick if (dmadebug & DDB_FOLLOW) 291*41480Smckusick printf("dmastop(%d)\n", unit); 292*41480Smckusick #endif 293*41480Smckusick dc->sc_timo = 0; 294*41480Smckusick DMA_CLEAR(dc); 295*41480Smckusick 296*41480Smckusick /* 297*41480Smckusick * We may get this interrupt after a device service routine 298*41480Smckusick * has freed the dma channel. So, ignore the intr if there's 299*41480Smckusick * nothing on the queue. 300*41480Smckusick */ 301*41480Smckusick dq = dmachan[unit].dq_forw; 302*41480Smckusick if (dq != &dmachan[unit]) { 303*41480Smckusick #if defined(HP370) 304*41480Smckusick /* 305*41480Smckusick * The 370 has an 64k external physical address cache. 306*41480Smckusick * In theory, we should only need to flush it when 307*41480Smckusick * DMAing to memory. 308*41480Smckusick */ 309*41480Smckusick if (ectype == EC_PHYS && (dc->sc_cmd & DMA_WRT) == 0) 310*41480Smckusick PCIA(); 311*41480Smckusick #endif 312*41480Smckusick (dq->dq_driver->d_done)(dq->dq_unit); 313*41480Smckusick } 314*41480Smckusick } 315*41480Smckusick 316*41480Smckusick int 317*41480Smckusick dmaintr() 318*41480Smckusick { 319*41480Smckusick register struct dma_softc *dc; 320*41480Smckusick register int i, j, stat; 321*41480Smckusick int found = 0; 322*41480Smckusick 323*41480Smckusick #ifdef DEBUG 324*41480Smckusick if (dmadebug & DDB_FOLLOW) 325*41480Smckusick printf("dmaintr\n"); 326*41480Smckusick #endif 327*41480Smckusick for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) { 328*41480Smckusick stat = DMA_STAT(dc); 329*41480Smckusick if ((stat & DMA_INTR) == 0) 330*41480Smckusick continue; 331*41480Smckusick found++; 332*41480Smckusick #ifdef DEBUG 333*41480Smckusick if (dmadebug & DDB_IO) { 334*41480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 335*41480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) 336*41480Smckusick printf("dmaintr: unit %d stat %x next %d\n", 337*41480Smckusick i, stat, dc->sc_cur+1); 338*41480Smckusick } 339*41480Smckusick if (stat & DMA_ARMED) 340*41480Smckusick printf("dma%d: intr when armed\n", i); 341*41480Smckusick #endif 342*41480Smckusick j = ++dc->sc_cur; 343*41480Smckusick if (j < DMAMAXIO && dc->sc_count[j]) { 344*41480Smckusick dc->sc_timo = 1; 345*41480Smckusick DMA_CLEAR(dc); 346*41480Smckusick DMA_ARM(dc, j); 347*41480Smckusick } else 348*41480Smckusick dmastop(i); 349*41480Smckusick } 350*41480Smckusick return(found); 351*41480Smckusick } 352*41480Smckusick 353*41480Smckusick void 354*41480Smckusick dmatimo() 355*41480Smckusick { 356*41480Smckusick register int i, s; 357*41480Smckusick register struct dma_softc *dc = &dma_softc[0]; 358*41480Smckusick 359*41480Smckusick for (i = 0; i < NDMA; i++, dc++) { 360*41480Smckusick s = splbio(); 361*41480Smckusick if (dc->sc_timo) { 362*41480Smckusick if (dc->sc_timo == 1) 363*41480Smckusick dc->sc_timo++; 364*41480Smckusick else 365*41480Smckusick dmastop(i); 366*41480Smckusick } 367*41480Smckusick splx(s); 368*41480Smckusick } 369*41480Smckusick timeout(dmatimo, (caddr_t)0, DMATIMO * hz); 370*41480Smckusick } 371