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