static void sa1100_irda_shutdown(struct sa1100_irda *si) { /* * Stop all DMA activity. */ sa1100_dma_stop(si->rxdma); sa1100_dma_stop(si->txdma); /* Disable the port. */ Ser2UTCR3 = 0; Ser2HSCR0 = 0; }
/* * FIR format interrupt service routine. We only have to * handle RX events; transmit events go via the TX DMA handler. * * No matter what, we disable RX, process, and the restart RX. */ static void sa1100_irda_fir_irq(struct net_device *dev) { struct sa1100_irda *si = dev->priv; /* * Stop RX DMA */ sa1100_dma_stop(si->rxdma); /* * Framing error - we throw away the packet completely. * Clearing RXE flushes the error conditions and data * from the fifo. */ if (Ser2HSSR0 & (HSSR0_FRE | HSSR0_RAB)) { si->stats.rx_errors++; if (Ser2HSSR0 & HSSR0_FRE) si->stats.rx_frame_errors++; /* * Clear out the DMA... */ Ser2HSCR0 = si->hscr0 | HSCR0_HSSP; /* * Clear selected status bits now, so we * don't miss them next time around. */ Ser2HSSR0 = HSSR0_FRE | HSSR0_RAB; } /* * Deal with any receive errors. The any of the lowest * 8 bytes in the FIFO may contain an error. We must read * them one by one. The "error" could even be the end of * packet! */ if (Ser2HSSR0 & HSSR0_EIF) sa1100_irda_fir_error(si, dev); /* * No matter what happens, we must restart reception. */ sa1100_irda_rx_dma_start(si); }
static int audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) { audio_state_t *state = (audio_state_t *)file->private_data; audio_stream_t *os = state->output_stream; audio_stream_t *is = state->input_stream; long val; /* dispatch based on command */ switch (cmd) { case OSS_GETVERSION: return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) return put_user(os->fragsize, (int *)arg); else return put_user(is->fragsize, (int *)arg); case SNDCTL_DSP_GETCAPS: val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP; if (is && os) val |= DSP_CAP_DUPLEX; return put_user(val, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, (long *) arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { int ret = audio_set_fragments(is, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } if (file->f_mode & FMODE_WRITE) { int ret = audio_set_fragments(os, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } return 0; case SNDCTL_DSP_SYNC: return audio_sync(file); case SNDCTL_DSP_SETDUPLEX: return 0; case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: val = 0; if (file->f_mode & FMODE_READ && is->active && !is->stopped) val |= PCM_ENABLE_INPUT; if (file->f_mode & FMODE_WRITE && os->active && !os->stopped) val |= PCM_ENABLE_OUTPUT; return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!is->active) { if (!is->buffers && audio_setup_buf(is)) return -ENOMEM; audio_prime_dma(is); } audio_check_tx_spin(state); if (is->stopped) { is->stopped = 0; sa1100_dma_resume(is->dma_ch); } } else { sa1100_dma_stop(is->dma_ch); is->stopped = 1; } } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { if (!os->active) { if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; if (os->mapped) audio_prime_dma(os); } if (os->stopped) { os->stopped = 0; sa1100_dma_resume(os->dma_ch); } } else { sa1100_dma_stop(os->dma_ch); os->stopped = 1; } } return 0; case SNDCTL_DSP_GETOPTR: case SNDCTL_DSP_GETIPTR: { count_info inf = { 0, }; audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is; audio_buf_t *b; dma_addr_t ptr; int bytecount, offset, flags; if ((s == is && !(file->f_mode & FMODE_READ)) || (s == os && !(file->f_mode & FMODE_WRITE))) return -EINVAL; if (s->active) { save_flags_cli(flags); if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) { offset = ptr - b->dma_addr; inf.ptr = (b - s->buffers) * s->fragsize + offset; } else offset = 0; bytecount = s->bytecount + offset; s->bytecount = -offset; inf.blocks = s->fragcount; s->fragcount = 0; restore_flags(flags); if (bytecount < 0) bytecount = 0; inf.bytes = bytecount; } return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_GETOSPACE: { audio_buf_info inf = { 0, }; int i; if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; for (i = 0; i < os->nbfrags; i++) { if (atomic_read(&os->buffers[i].sem.count) > 0) { if (os->buffers[i].size == 0) inf.fragments++; inf.bytes += os->fragsize - os->buffers[i].size; } } inf.fragstotal = os->nbfrags; inf.fragsize = os->fragsize; return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_GETISPACE: { audio_buf_info inf = { 0, }; int i; if (!(file->f_mode & FMODE_READ)) return -EINVAL; if (!is->buffers && audio_setup_buf(is)) return -ENOMEM; for (i = 0; i < is->nbfrags; i++) { if (atomic_read(&is->buffers[i].sem.count) > 0) { if (is->buffers[i].size == is->fragsize) inf.fragments++; inf.bytes += is->buffers[i].size; } } inf.fragstotal = is->nbfrags; inf.fragsize = is->fragsize; return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; return 0; case SNDCTL_DSP_GETODELAY: { int count = 0; int i; int flags; audio_buf_t *b; dma_addr_t ptr; if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; save_flags_cli(flags); for (i = 0; i < os->nbfrags; i++) { /* if contains data */ if (atomic_read(&os->buffers[i].sem.count) <= 0) { count += os->fragsize; } } if (sa1100_dma_get_current(os->dma_ch, (void *)&b, &ptr) == 0) count -= ptr - b->dma_addr; restore_flags(flags); return put_user(count, (int *)arg); } case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_READ) { if (state->tx_spinning) { sa1100_dma_set_spin(os->dma_ch, 0, 0); state->tx_spinning = 0; } audio_reset_buf(is); } if (file->f_mode & FMODE_WRITE) { audio_reset_buf(os); } return 0; default: /* * Let the client of this module handle the * non generic ioctls */ return state->client_ioctl(inode, file, cmd, arg); } return 0; }
/* * Set the IrDA communications speed. */ static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed) { unsigned long flags; int brd, ret = -EINVAL; switch (speed) { case 9600: case 19200: case 38400: case 57600: case 115200: brd = 3686400 / (16 * speed) - 1; /* * Stop the receive DMA. */ if (IS_FIR(si)) sa1100_dma_stop(si->rxdma); local_irq_save(flags); Ser2UTCR3 = 0; Ser2HSCR0 = HSCR0_UART; Ser2UTCR1 = brd >> 8; Ser2UTCR2 = brd; /* * Clear status register */ Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE; if (machine_is_assabet()) ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL); if (machine_is_h3600()) clr_h3600_egpio(EGPIO_H3600_IR_FSEL); if (machine_is_yopy()) PPSR &= ~GPIO_IRDA_FIR; si->speed = speed; local_irq_restore(flags); ret = 0; break; case 4000000: save_flags(flags); cli(); si->hscr0 = 0; Ser2HSSR0 = 0xff; Ser2HSCR0 = si->hscr0 | HSCR0_HSSP; Ser2UTCR3 = 0; si->speed = speed; if (machine_is_assabet()) ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL); if (machine_is_h3600()) set_h3600_egpio(EGPIO_H3600_IR_FSEL); if (machine_is_yopy()) PPSR |= GPIO_IRDA_FIR; sa1100_irda_rx_alloc(si); sa1100_irda_rx_dma_start(si); restore_flags(flags); break; default: break; } return ret; }