* Setup a DMA channel's bounce buffer. */
| 85 | * Setup a DMA channel's bounce buffer. |
| 86 | */ |
| 87 | int |
| 88 | isa_dma_init(int chan, u_int bouncebufsize, int flag) |
| 89 | { |
| 90 | void *buf; |
| 91 | int contig; |
| 92 | |
| 93 | #ifdef DIAGNOSTIC |
| 94 | if (chan & ~VALID_DMA_MASK) |
| 95 | panic("isa_dma_init: channel out of range"); |
| 96 | #endif |
| 97 | |
| 98 | /* Try malloc() first. It works better if it works. */ |
| 99 | buf = malloc(bouncebufsize, M_DEVBUF, flag); |
| 100 | if (buf != NULL) { |
| 101 | if (isa_dmarangecheck(buf, bouncebufsize, chan) != 0) { |
| 102 | free(buf, M_DEVBUF); |
| 103 | buf = NULL; |
| 104 | } |
| 105 | contig = 0; |
| 106 | } |
| 107 | |
| 108 | if (buf == NULL) { |
| 109 | buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful, |
| 110 | 1ul, chan & 4 ? 0x20000ul : 0x10000ul); |
| 111 | contig = 1; |
| 112 | } |
| 113 | |
| 114 | if (buf == NULL) |
| 115 | return (ENOMEM); |
| 116 | |
| 117 | mtx_lock(&isa_dma_lock); |
| 118 | /* |
| 119 | * If a DMA channel is shared, both drivers have to call isa_dma_init |
| 120 | * since they don't know that the other driver will do it. |
| 121 | * Just return if we're already set up good. |
| 122 | * XXX: this only works if they agree on the bouncebuf size. This |
| 123 | * XXX: is typically the case since they are multiple instances of |
| 124 | * XXX: the same driver. |
| 125 | */ |
| 126 | if (dma_bouncebuf[chan] != NULL) { |
| 127 | if (contig) |
| 128 | contigfree(buf, bouncebufsize, M_DEVBUF); |
| 129 | else |
| 130 | free(buf, M_DEVBUF); |
| 131 | mtx_unlock(&isa_dma_lock); |
| 132 | return (0); |
| 133 | } |
| 134 | |
| 135 | dma_bouncebufsize[chan] = bouncebufsize; |
| 136 | dma_bouncebuf[chan] = buf; |
| 137 | |
| 138 | mtx_unlock(&isa_dma_lock); |
| 139 | |
| 140 | return (0); |
| 141 | } |
| 142 | |
| 143 | /* |
| 144 | * Register a DMA channel's usage. Usually called from a device driver |
nothing calls this directly
no test coverage detected