📄 wavfront.c
字号:
i, cmd, wfcmd->action); return 1; } DPRINT (WF_DEBUG_DATA, "write[%d] = 0x%x\n", i, wbuf[i]); } } if (wfcmd->read_cnt > 0) { DPRINT (WF_DEBUG_DATA, "reading %d ints " "for 0x%x\n", wfcmd->read_cnt, cmd); for (i = 0; i < wfcmd->read_cnt; i++) { if ((c = wavefront_read()) == -1) { DPRINT (WF_DEBUG_IO, "bad read for byte " "%d of 0x%x [%s].\n", i, cmd, wfcmd->action); return 1; } /* Now handle errors. Lots of special cases here */ if (c == 0xff) { if ((c = wavefront_read ()) == -1) { DPRINT (WF_DEBUG_IO, "bad read for " "error byte at " "read byte %d " "of 0x%x [%s].\n", i, cmd, wfcmd->action); return 1; } /* Can you believe this madness ? */ if (c == 1 && wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) { rbuf[0] = WF_ST_EMPTY; return (0); } else if (c == 3 && wfcmd->cmd == WFC_UPLOAD_PATCH) { return 3; } else if (c == 1 && wfcmd->cmd == WFC_UPLOAD_PROGRAM) { return 1; } else { DPRINT (WF_DEBUG_IO, "error %d (%s) " "during " "read for byte " "%d of 0x%x " "[%s].\n", c, wavefront_errorstr (c), i, cmd, wfcmd->action); return 1; } } else { rbuf[i] = c; } DPRINT (WF_DEBUG_DATA, "read[%d] = 0x%x\n",i, rbuf[i]); } } if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) { DPRINT (WF_DEBUG_CMD, "reading ACK for 0x%x\n", cmd); /* Some commands need an ACK, but return zero instead of the standard value. */ if ((ack = wavefront_read()) == 0) { ack = WF_ACK; } if (ack != WF_ACK) { if (ack == -1) { DPRINT (WF_DEBUG_IO, "cannot read ack for " "0x%x [%s].\n", cmd, wfcmd->action); return 1; } else { int err = -1; /* something unknown */ if (ack == 0xff) { /* explicit error */ if ((err = wavefront_read ()) == -1) { DPRINT (WF_DEBUG_DATA, "cannot read err " "for 0x%x [%s].\n", cmd, wfcmd->action); } } DPRINT (WF_DEBUG_IO, "0x%x [%s] " "failed (0x%x, 0x%x, %s)\n", cmd, wfcmd->action, ack, err, wavefront_errorstr (err)); return -err; } } DPRINT (WF_DEBUG_DATA, "ack received " "for 0x%x [%s]\n", cmd, wfcmd->action); } else { DPRINT (WF_DEBUG_CMD, "0x%x [%s] does not need " "ACK (%d,%d,%d)\n", cmd, wfcmd->action, wfcmd->read_cnt, wfcmd->write_cnt, wfcmd->need_ack); } return 0; }/***********************************************************************WaveFront: data munging Things here are weird. All data written to the board cannot have its most significant bit set. Any data item with values potentially > 0x7F (127) must be split across multiple bytes.Sometimes, we need to munge numeric values that are represented onthe x86 side as 8-32 bit values. Sometimes, we need to munge datathat is represented on the x86 side as an array of bytes. The mostefficient approach to handling both cases seems to be to use 2different functions for munging and 2 for de-munging. This avoidsweird casting and worrying about bit-level offsets.**********************************************************************/static unsigned char *munge_int32 (unsigned int src, unsigned char *dst, unsigned int dst_size){ int i; for (i = 0;i < dst_size; i++) { *dst = src & 0x7F; /* Mask high bit of LSB */ src = src >> 7; /* Rotate Right 7 bits */ /* Note: we leave the upper bits in place */ dst++; }; return dst;};static int demunge_int32 (unsigned char* src, int src_size){ int i; int outval = 0; for (i = src_size - 1; i >= 0; i--) { outval=(outval<<7)+src[i]; } return outval;};static unsigned char *munge_buf (unsigned char *src, unsigned char *dst, unsigned int dst_size){ int i; unsigned int last = dst_size / 2; for (i = 0; i < last; i++) { *dst++ = src[i] & 0x7f; *dst++ = src[i] >> 7; } return dst;}static unsigned char *demunge_buf (unsigned char *src, unsigned char *dst, unsigned int src_bytes){ int i; unsigned char *end = src + src_bytes; end = src + src_bytes; /* NOTE: src and dst *CAN* point to the same address */ for (i = 0; src != end; i++) { dst[i] = *src++; dst[i] |= (*src++)<<7; } return dst;}/***********************************************************************WaveFront: sample, patch and program management.***********************************************************************/static intwavefront_delete_sample (int sample_num){ unsigned char wbuf[2]; int x; wbuf[0] = sample_num & 0x7f; wbuf[1] = sample_num >> 7; if ((x = wavefront_cmd (WFC_DELETE_SAMPLE, 0, wbuf)) == 0) { dev.sample_status[sample_num] = WF_ST_EMPTY; } return x;}static intwavefront_get_sample_status (int assume_rom){ int i; unsigned char rbuf[32], wbuf[32]; unsigned int sc_real, sc_alias, sc_multi; /* check sample status */ if (wavefront_cmd (WFC_GET_NSAMPLES, rbuf, wbuf)) { printk (KERN_WARNING LOGNAME "cannot request sample count.\n"); return -1; } sc_real = sc_alias = sc_multi = dev.samples_used = 0; for (i = 0; i < WF_MAX_SAMPLE; i++) { wbuf[0] = i & 0x7f; wbuf[1] = i >> 7; if (wavefront_cmd (WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { printk (KERN_WARNING LOGNAME "cannot identify sample " "type of slot %d\n", i); dev.sample_status[i] = WF_ST_EMPTY; continue; } dev.sample_status[i] = (WF_SLOT_FILLED|rbuf[0]); if (assume_rom) { dev.sample_status[i] |= WF_SLOT_ROM; } switch (rbuf[0] & WF_ST_MASK) { case WF_ST_SAMPLE: sc_real++; break; case WF_ST_MULTISAMPLE: sc_multi++; break; case WF_ST_ALIAS: sc_alias++; break; case WF_ST_EMPTY: break; default: printk (KERN_WARNING LOGNAME "unknown sample type for " "slot %d (0x%x)\n", i, rbuf[0]); } if (rbuf[0] != WF_ST_EMPTY) { dev.samples_used++; } } printk (KERN_INFO LOGNAME "%d samples used (%d real, %d aliases, %d multi), " "%d empty\n", dev.samples_used, sc_real, sc_alias, sc_multi, WF_MAX_SAMPLE - dev.samples_used); return (0);}static intwavefront_get_patch_status (void){ unsigned char patchbuf[WF_PATCH_BYTES]; unsigned char patchnum[2]; wavefront_patch *p; int i, x, cnt, cnt2; for (i = 0; i < WF_MAX_PATCH; i++) { patchnum[0] = i & 0x7f; patchnum[1] = i >> 7; if ((x = wavefront_cmd (WFC_UPLOAD_PATCH, patchbuf, patchnum)) == 0) { dev.patch_status[i] |= WF_SLOT_FILLED; p = (wavefront_patch *) patchbuf; dev.sample_status [p->sample_number|(p->sample_msb<<7)] |= WF_SLOT_USED; } else if (x == 3) { /* Bad patch number */ dev.patch_status[i] = 0; } else { printk (KERN_ERR LOGNAME "upload patch " "error 0x%x\n", x); dev.patch_status[i] = 0; return 1; } } /* program status has already filled in slot_used bits */ for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) { if (dev.patch_status[i] & WF_SLOT_FILLED) { cnt++; } if (dev.patch_status[i] & WF_SLOT_USED) { cnt2++; } } printk (KERN_INFO LOGNAME "%d patch slots filled, %d in use\n", cnt, cnt2); return (0);}static intwavefront_get_program_status (void){ unsigned char progbuf[WF_PROGRAM_BYTES]; wavefront_program prog; unsigned char prognum; int i, x, l, cnt; for (i = 0; i < WF_MAX_PROGRAM; i++) { prognum = i; if ((x = wavefront_cmd (WFC_UPLOAD_PROGRAM, progbuf, &prognum)) == 0) { dev.prog_status[i] |= WF_SLOT_USED; demunge_buf (progbuf, (unsigned char *) &prog, WF_PROGRAM_BYTES); for (l = 0; l < WF_NUM_LAYERS; l++) { if (prog.layer[l].mute) { dev.patch_status [prog.layer[l].patch_number] |= WF_SLOT_USED; } } } else if (x == 1) { /* Bad program number */ dev.prog_status[i] = 0; } else { printk (KERN_ERR LOGNAME "upload program " "error 0x%x\n", x); dev.prog_status[i] = 0; } } for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) { if (dev.prog_status[i]) { cnt++; } } printk (KERN_INFO LOGNAME "%d programs slots in use\n", cnt); return (0);}static intwavefront_send_patch (wavefront_patch_info *header){ unsigned char buf[WF_PATCH_BYTES+2]; unsigned char *bptr; DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n", header->number); dev.patch_status[header->number] |= WF_SLOT_FILLED; bptr = buf; bptr = munge_int32 (header->number, buf, 2); munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); if (wavefront_cmd (WFC_DOWNLOAD_PATCH, 0, buf)) { printk (KERN_ERR LOGNAME "download patch failed\n"); return -(EIO); } return (0);}static intwavefront_send_program (wavefront_patch_info *header){ unsigned char buf[WF_PROGRAM_BYTES+1]; int i; DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n", header->number); dev.prog_status[header->number] = WF_SLOT_USED; /* XXX need to zero existing SLOT_USED bit for program_status[i] where `i' is the program that's being (potentially) overwritten. */ for (i = 0; i < WF_NUM_LAYERS; i++) { if (header->hdr.pr.layer[i].mute) { dev.patch_status[header->hdr.pr.layer[i].patch_number] |= WF_SLOT_USED; /* XXX need to mark SLOT_USED for sample used by patch_number, but this means we have to load it. Ick. */ } } buf[0] = header->number; munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES); if (wavefront_cmd (WFC_DOWNLOAD_PROGRAM, 0, buf)) { printk (KERN_WARNING LOGNAME "download patch failed\n"); return -(EIO); } return (0);}static intwavefront_freemem (void){ char rbuf[8]; if (wavefront_cmd (WFC_REPORT_FREE_MEMORY, rbuf, 0)) { printk (KERN_WARNING LOGNAME "can't get memory stats.\n"); return -1; } else { return demunge_int32 (rbuf, 4); }}static intwavefront_send_sample (wavefront_patch_info *header, UINT16 *dataptr, int data_is_unsigned){ /* samples are downloaded via a 16-bit wide i/o port (you could think of it as 2 adjacent 8-bit wide ports but its less efficient that way). therefore, all the blocksizes and so forth listed in the documentation, and used conventionally to refer to sample sizes, which are given in 8-bit units (bytes), need to be divided by 2. */ UINT16 sample_short; UINT32 length; UINT16 *data_end = 0; unsigned int i; const int max_blksize = 4096/2; unsigned int written; unsigned int blocksize; int dma_ack; int blocknum; unsigned char sample_hdr[WF_SAMPLE_HDR_BYTES]; unsigned char *shptr; int skip = 0; int initial_skip = 0; DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, " "type %d, %d bytes from 0x%x\n", header->size ? "" : "header ", header->number, header->subkey, header->size, (int) header->dataptr); if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) { int x;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -