📄 wavfront.c
字号:
static intwavefront_cmd (int cmd, unsigned char *rbuf, unsigned char *wbuf){ int ack; int i; int c; wavefront_command *wfcmd; if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) { printk (KERN_WARNING LOGNAME "command 0x%x not supported.\n", cmd); return 1; } /* Hack to handle the one variable-size write command. See wavefront_send_multisample() for the other half of this gross and ugly strategy. */ if (cmd == WFC_DOWNLOAD_MULTISAMPLE) { wfcmd->write_cnt = (unsigned int) rbuf; rbuf = 0; } DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n", cmd, wfcmd->action, wfcmd->read_cnt, wfcmd->write_cnt, wfcmd->need_ack); if (wavefront_write (cmd)) { DPRINT ((WF_DEBUG_IO|WF_DEBUG_CMD), "cannot request " "0x%x [%s].\n", cmd, wfcmd->action); return 1; } if (wfcmd->write_cnt > 0) { DPRINT (WF_DEBUG_DATA, "writing %d bytes " "for 0x%x\n", wfcmd->write_cnt, cmd); for (i = 0; i < wfcmd->write_cnt; i++) { if (wavefront_write (wbuf[i])) { DPRINT (WF_DEBUG_IO, "bad write for byte " "%d of 0x%x [%s].\n", 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 wierd. 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 avoidswierd 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){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -