1 /* $OpenBSD: dbdma.c,v 1.11 2015/09/08 08:29:35 deraadt Exp $ */ 2 /* $NetBSD: dbdma.c,v 1.2 1998/08/21 16:13:28 tsubai Exp $ */ 3 4 /* 5 * Copyright 1991-1998 by Open Software Foundation, Inc. 6 * All Rights Reserved 7 * 8 * Permission to use, copy, modify, and distribute this software and 9 * its documentation for any purpose and without fee is hereby granted, 10 * provided that the above copyright notice appears in all copies and 11 * that both the copyright notice and this permission notice appear in 12 * supporting documentation. 13 * 14 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 16 * FOR A PARTICULAR PURPOSE. 17 * 18 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 21 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 22 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 23 * 24 */ 25 26 #include <sys/param.h> 27 #include <sys/malloc.h> 28 #include <sys/systm.h> 29 30 #include <uvm/uvm_extern.h> 31 32 #include <machine/bus.h> 33 #include <macppc/dev/dbdma.h> 34 35 dbdma_command_t *dbdma_alloc_commands = NULL; 36 37 void 38 dbdma_start(dbdma_regmap_t *dmap, dbdma_t dt) 39 { 40 u_int32_t addr = dt->d_paddr; 41 42 DBDMA_ST4_ENDIAN(&dmap->d_intselect, DBDMA_CLEAR_CNTRL((0xffff))); 43 DBDMA_ST4_ENDIAN(&dmap->d_control, DBDMA_CLEAR_CNTRL(( 44 DBDMA_CNTRL_ACTIVE | 45 DBDMA_CNTRL_DEAD | 46 DBDMA_CNTRL_WAKE | 47 DBDMA_CNTRL_FLUSH | 48 DBDMA_CNTRL_PAUSE | 49 DBDMA_CNTRL_RUN))); 50 51 /* XXX time-bind it? */ 52 do { 53 delay(10); 54 } while (DBDMA_LD4_ENDIAN(&dmap->d_status) & DBDMA_CNTRL_ACTIVE); 55 56 57 DBDMA_ST4_ENDIAN(&dmap->d_cmdptrhi, 0); /* 64-bit not yet */ 58 DBDMA_ST4_ENDIAN(&dmap->d_cmdptrlo, addr); 59 60 DBDMA_ST4_ENDIAN(&dmap->d_control, 61 DBDMA_SET_CNTRL(DBDMA_CNTRL_RUN|DBDMA_CNTRL_WAKE)| 62 DBDMA_CLEAR_CNTRL(DBDMA_CNTRL_PAUSE|DBDMA_CNTRL_DEAD) ); 63 } 64 65 void 66 dbdma_stop(dbdma_regmap_t *dmap) 67 { 68 DBDMA_ST4_ENDIAN(&dmap->d_control, DBDMA_CLEAR_CNTRL(DBDMA_CNTRL_RUN) | 69 DBDMA_SET_CNTRL(DBDMA_CNTRL_FLUSH)); 70 71 while (DBDMA_LD4_ENDIAN(&dmap->d_status) & 72 (DBDMA_CNTRL_ACTIVE|DBDMA_CNTRL_FLUSH)); 73 } 74 75 void 76 dbdma_flush(dbdma_regmap_t *dmap) 77 { 78 DBDMA_ST4_ENDIAN(&dmap->d_control, DBDMA_SET_CNTRL(DBDMA_CNTRL_FLUSH)); 79 80 /* XXX time-bind it? */ 81 while (DBDMA_LD4_ENDIAN(&dmap->d_status) & (DBDMA_CNTRL_FLUSH)); 82 } 83 84 void 85 dbdma_reset(dbdma_regmap_t *dmap) 86 { 87 DBDMA_ST4_ENDIAN(&dmap->d_control, 88 DBDMA_CLEAR_CNTRL( (DBDMA_CNTRL_ACTIVE | 89 DBDMA_CNTRL_DEAD | 90 DBDMA_CNTRL_WAKE | 91 DBDMA_CNTRL_FLUSH | 92 DBDMA_CNTRL_PAUSE | 93 DBDMA_CNTRL_RUN ))); 94 95 /* XXX time-bind it? */ 96 while (DBDMA_LD4_ENDIAN(&dmap->d_status) & DBDMA_CNTRL_RUN); 97 } 98 99 void 100 dbdma_continue(dbdma_regmap_t *dmap) 101 { 102 DBDMA_ST4_ENDIAN(&dmap->d_control, 103 DBDMA_SET_CNTRL(DBDMA_CNTRL_RUN | DBDMA_CNTRL_WAKE) | 104 DBDMA_CLEAR_CNTRL(DBDMA_CNTRL_PAUSE | DBDMA_CNTRL_DEAD)); 105 } 106 107 void 108 dbdma_pause(dbdma_regmap_t *dmap) 109 { 110 DBDMA_ST4_ENDIAN(&dmap->d_control,DBDMA_SET_CNTRL(DBDMA_CNTRL_PAUSE)); 111 112 /* XXX time-bind it? */ 113 while (DBDMA_LD4_ENDIAN(&dmap->d_status) & DBDMA_CNTRL_ACTIVE); 114 } 115 116 dbdma_t 117 dbdma_alloc(bus_dma_tag_t dmat, int size) 118 { 119 dbdma_t dt; 120 int error; 121 122 dt = malloc(sizeof *dt, M_DEVBUF, M_NOWAIT | M_ZERO); 123 if (!dt) 124 return (dt); 125 126 dt->d_size = size *= sizeof(dbdma_command_t); 127 dt->d_dmat = dmat; 128 if ((error = bus_dmamem_alloc(dmat, size, NBPG, 0, dt->d_segs, 129 1, &dt->d_nsegs, BUS_DMA_NOWAIT)) != 0) { 130 printf("dbdma: unable to allocate dma, error = %d\n", error); 131 } else if ((error = bus_dmamem_map(dmat, dt->d_segs, dt->d_nsegs, size, 132 (caddr_t *)&dt->d_addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 133 printf("dbdma: unable to map dma, error = %d\n", error); 134 } else if ((error = bus_dmamap_create(dmat, dt->d_size, 1, 135 dt->d_size, 0, BUS_DMA_NOWAIT, &dt->d_map)) != 0) { 136 printf("dbdma: unable to create dma map, error = %d\n", error); 137 } else if ((error = bus_dmamap_load_raw(dmat, dt->d_map, 138 dt->d_segs, dt->d_nsegs, size, BUS_DMA_NOWAIT)) != 0) { 139 printf("dbdma: unable to load dma map, error = %d\n", error); 140 } else 141 return dt; 142 143 dbdma_free(dt); 144 return (NULL); 145 } 146 147 void 148 dbdma_free(dbdma_t dt) 149 { 150 if (dt->d_map) 151 bus_dmamap_destroy(dt->d_dmat, dt->d_map); 152 if (dt->d_addr) 153 bus_dmamem_unmap(dt->d_dmat, (caddr_t)dt->d_addr, dt->d_size); 154 if (dt->d_nsegs) 155 bus_dmamem_free(dt->d_dmat, dt->d_segs, dt->d_nsegs); 156 free(dt, M_DEVBUF, sizeof *dt); 157 } 158