00001
00002
00003
00004
00005
00006
00007 #include <sys/mman.h>
00008 #include "edtinc.h"
00009 #include "libpdma.h"
00010
00011
00012 u_int
00013 regswap(u_int val)
00014 {
00015 #ifdef __sparc
00016
00017 val = ((val & 0xFF00FF00) >> 8) | ((val & 0x00FF00FF) << 8);
00018
00019
00020 val = ((val & 0xFFFF0000) >> 16) | ((val & 0x0000FFFF) << 16);
00021 #endif
00022
00023 return val;
00024 }
00025
00026
00027
00028 int
00029 pdma_init(EdtDev *edt_p, int bufsize, int numbufs, u_char **bufs)
00030 {
00031 u_int mode;
00032 void * mapaddr;
00033 Pdma_t *p;
00034
00035 if (bufsize > PDMA_MAX_SIZE)
00036 {
00037 fprintf(stderr, "pdma_init: bufsize (%d) exceeds PDMA_MAX_SIZE (%d)\n",
00038 bufsize, PDMA_MAX_SIZE);
00039 return -1;
00040 }
00041
00042 if (numbufs != 1)
00043 {
00044 fprintf(stderr, "pdma_init: number of buffers must be 1.\nContinuing with one buffer.\n");
00045 numbufs = 1;
00046 }
00047
00048 if ((edt_p->Pdma_p = (Pdma_t *) edt_alloc(sizeof(Pdma_t))) == NULL)
00049 {
00050 return -1;
00051 }
00052
00053 p = (Pdma_t *) edt_p->Pdma_p;
00054 memset(p, 0, sizeof(Pdma_t));
00055
00056
00057
00058
00059
00060
00061 if ((mapaddr = (void *) edt_mapmem(edt_p, 0, 256)) == NULL)
00062 return -1;
00063
00064 p->dmacmd = (u_int *) ((u_char *)mapaddr + (EDT_SG_NXT_CNT & 0xff));
00065 p->dmaaddr = (u_int *) ((u_char *)mapaddr + (EDT_SG_NXT_ADDR & 0xff));
00066 p->dmacfg = (u_int *) ((u_char *)mapaddr + (EDT_DMA_CFG & 0xff));
00067 p->dmacnt = (u_int *) ((u_char *)mapaddr + (EDT_DMA_CUR_CNT & 0xff));
00068 p->off_p = (u_char *) ((u_char *)mapaddr + (EDT_REMOTE_OFFSET & 0xff));
00069 p->data_p = (u_char *) ((u_char *)mapaddr + (EDT_REMOTE_DATA & 0xff));
00070
00071
00072
00073
00074
00075
00076
00077 mode = 1;
00078 edt_ioctl(edt_p, EDTS_PDMA_MODE, &mode);
00079
00080 if (edt_configure_ring_buffers(edt_p, bufsize, numbufs, EDT_WRITE, bufs) != 0)
00081 {
00082 edt_free((u_char *)p);
00083 return -1;
00084 }
00085
00086 p->pdma_size = bufsize;
00087 p->pdma_databufs = edt_buffer_addresses(edt_p);
00088
00089
00090
00091
00092
00093 if ((mapaddr = (volatile caddr_t) mmap((caddr_t)0, PDMA_SIZE,
00094 PROT_READ|PROT_WRITE, MAP_SHARED, edt_p->fd, PDMA_OFFSET)) == NULL)
00095 {
00096 edt_free((u_char *)p);
00097 return -1;
00098 }
00099 p->dma_sglist = (u_int *) mapaddr;
00100
00101 memcpy((u_char *)p->dma_sglist_copy, (u_char *)p->dma_sglist, PDMA_SIZE);
00102
00103
00104
00105
00106 {
00107 edt_buf sg_args;
00108
00109 sg_args.desc = EDT_SGTODO_FIRST_SG;
00110 sg_args.value = 0;
00111 edt_ioctl(edt_p, EDTG_SGINFO, &sg_args);
00112 p->sg_paddr = (u_int) sg_args.value;
00113 }
00114
00115 p->sv_dma_cfg = *p->dmacfg;
00116 p->dma_intr_en = 1;
00117
00118
00119
00120
00121
00122
00123
00124 edt_start_buffers(edt_p, 0);
00125
00126 return 0;
00127 }
00128
00129
00130 int
00131 pdma_close(EdtDev *edt_p)
00132 {
00133 int mode = 0;
00134 Pdma_t *p = (Pdma_t *) edt_p->Pdma_p;
00135 extern int errno;
00136
00137 if (p == NULL)
00138 {
00139 errno = EINVAL;
00140 return -1;
00141 }
00142
00143 if (p && p->dma_sglist)
00144 munmap((caddr_t) p->dma_sglist, PDMA_SIZE);
00145
00146 edt_disable_ring_buffers(edt_p);
00147 edt_ioctl(edt_p, EDTS_PDMA_MODE, &mode);
00148 edt_free((u_char *)edt_p->Pdma_p);
00149 edt_p->Pdma_p = NULL;
00150
00151 return 0;
00152 }
00153
00154
00155
00156
00157
00158 int
00159 pdma_set_size(EdtDev *edt_p, int size)
00160 {
00161 int i;
00162 Pdma_t *p = (Pdma_t *) edt_p->Pdma_p;
00163 extern int errno;
00164
00165 if (p == NULL)
00166 {
00167 errno = EINVAL;
00168 return -1;
00169 }
00170
00171
00172
00173
00174 if (size > p->pdma_size || size != (size & ~0x3))
00175 {
00176 errno = EINVAL;
00177 return -1;
00178 }
00179
00180
00181 memcpy((u_char *)p->dma_sglist, (u_char *)p->dma_sglist_copy, PDMA_SIZE);
00182
00183
00184
00185 p->dma_count = 0;
00186 for (i = 1; size > 0; i += 2)
00187 {
00188 if (size > regswap(p->dma_sglist[i]))
00189 {
00190 size -= regswap(p->dma_sglist[i]);
00191 ++ p->dma_count;
00192 }
00193 else
00194 {
00195 p->dma_sglist[i] = regswap(size | EDT_LIST_PAGEINT);
00196 ++ p->dma_count;
00197 break;
00198 }
00199 }
00200
00201 if ((p->dma_count << 3) > PDMA_PAGESIZE)
00202 p->dma_count = PDMA_PAGESIZE >> 3;
00203
00204 return 0;
00205 }
00206
00207
00208 int
00209 pdma_start_dma(EdtDev *edt_p)
00210 {
00211 Pdma_t *p = (Pdma_t *) edt_p->Pdma_p;
00212 u_int dmacmd_reg;
00213 u_int dmacfg_reg, tmp;
00214 int rw = 1, burst = 1;
00215 extern int errno;
00216
00217 if (p == NULL)
00218 {
00219 errno = EINVAL;
00220 return -1;
00221 }
00222
00223 dmacmd_reg = EDT_DMA_START | ((rw) ? EDT_DMA_MEM_RD : 0)
00224 | ((burst) ? EDT_BURST_EN : 0)
00225 | ((p->dma_intr_en) ? EDT_EN_MN_DONE : 0);
00226
00227 dmacmd_reg |= (p->dma_count << 3);
00228
00229 dmacfg_reg = p->sv_dma_cfg
00230 | ((burst) ? regswap(EDT_RFIFO_ENB) : 0)
00231 | ((p->dma_intr_en) ? regswap(EDT_PCI_EN_INTR) : 0);
00232
00233 *p->dmacfg = regswap(dmacfg_reg);
00234 tmp = *p->dmacfg;
00235
00236 *p->dmaaddr = regswap(p->sg_paddr);
00237 tmp = *p->dmaaddr;
00238
00239 *p->dmacmd = regswap(dmacmd_reg);
00240 tmp = *p->dmacmd;
00241
00242 return 0;
00243 }
00244
00245
00246 int
00247 pdma_flush_fifo(EdtDev * edt_p)
00248 {
00249 unsigned char cmd;
00250 unsigned int dmy;
00251 Pdma_t *p = (Pdma_t *) edt_p->Pdma_p;
00252 extern int errno;
00253
00254 if (p == NULL)
00255 {
00256 errno = EINVAL;
00257 return -1;
00258 }
00259
00260
00261 #if 0
00262
00263 dmacfg_copy = regswap(*dmacfg);
00264 dmacfg_copy &= (~EDT_RFIFO_ENB);
00265 *dmacfg = regswap(dmacfg_copy);
00266 dmacfg_copy = regswap(*dmacfg);
00267 #endif
00268
00269
00270
00271 *p->off_p = PCD_CMD & 0xff;
00272 dmy = *p->off_p;
00273 cmd = *p->data_p;
00274 cmd &= ~PCD_ENABLE;
00275 *p->data_p = cmd;
00276 dmy = *p->data_p;
00277 cmd |= PCD_ENABLE;
00278 *p->data_p = cmd;
00279 dmy = *p->data_p;
00280
00281
00282
00283 #if 0
00284
00285 dmacfg_copy |= (EDT_RFIFO_ENB);
00286 *dmacfg = regswap(dmacfg_copy);
00287 dmacfg_copy = regswap(*dmacfg);
00288 #endif
00289
00290 return 0;
00291 }
00292
00293 int
00294 pdma_abort_dma(EdtDev * edt_p)
00295 {
00296 Pdma_t *p = (Pdma_t *) edt_p->Pdma_p;
00297 u_int dmacmd_reg = regswap(*p->dmacmd);
00298 extern int errno;
00299
00300 if (p == NULL)
00301 {
00302 errno = EINVAL;
00303 return -1;
00304 }
00305
00306 dmacmd_reg |= EDT_DMA_ABORT;
00307 *p->dmacmd = regswap(dmacmd_reg);
00308 dmacmd_reg = regswap(*p->dmacmd);
00309
00310 return 0;
00311 }
00312
00313 int
00314 pdma_write_databuf(EdtDev *edt_p, int bufnum, void *buf, int size)
00315 {
00316 Pdma_t *p = (Pdma_t *) edt_p->Pdma_p;
00317 extern int errno;
00318
00319 if (p == NULL)
00320 {
00321 errno = EINVAL;
00322 return -1;
00323 }
00324
00325 printf("pdma_write_databuf pdma_size %d size %d\n", p->pdma_size, size);
00326 fflush(stdout);
00327 if (size > p->pdma_size)
00328 {
00329 errno = EINVAL;
00330 return -1;
00331 }
00332
00333 memcpy(p->pdma_databufs[bufnum], buf, size);
00334
00335 return size;
00336 }
00337
00338
00339 void
00340 pdma_dmaint_enable(EdtDev * edt_p, int enable)
00341 {
00342 Pdma_t *p = (Pdma_t *) edt_p->Pdma_p;
00343
00344 p->dma_intr_en = enable;
00345 }
00346