static int bfin_sir_resume(struct platform_device *pdev) { struct bfin_sir_port *sir_port; struct net_device *dev; struct bfin_sir_self *self; struct bfin_sir_port *port; sir_port = platform_get_drvdata(pdev); if (!sir_port) return 0; dev = sir_port->dev; self = netdev_priv(dev); port = self->sir_port; if (self->open) { if (self->newspeed) { self->speed = self->newspeed; self->newspeed = 0; } bfin_sir_startup(port, dev); bfin_sir_set_speed(port, 9600); bfin_sir_enable_rx(port); netif_device_attach(dev); } return 0; }
static irqreturn_t bfin_sir_dma_tx_int(int irq, void *dev_id) { struct net_device *dev = dev_id; struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; spin_lock(&self->lock); if (!(get_dma_curr_irqstat(port->tx_dma_channel) & DMA_RUN)) { clear_dma_irqstat(port->tx_dma_channel); bfin_sir_stop_tx(port); self->stats.tx_packets++; self->stats.tx_bytes += self->tx_buff.len; self->tx_buff.len = 0; if (self->newspeed) { bfin_sir_set_speed(port, self->newspeed); self->speed = self->newspeed; self->newspeed = 0; } bfin_sir_enable_rx(port); /* I'm hungry! */ netif_wake_queue(dev); port->tx_done = 1; } spin_unlock(&self->lock); return IRQ_HANDLED; }
static void bfin_sir_dma_tx_chars(struct net_device *dev) { struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; if (!port->tx_done) return; port->tx_done = 0; if (self->tx_buff.len == 0) { self->stats.tx_packets++; if (self->newspeed) { bfin_sir_set_speed(port, self->newspeed); self->speed = self->newspeed; self->newspeed = 0; } bfin_sir_enable_rx(port); port->tx_done = 1; netif_wake_queue(dev); return; } blackfin_dcache_flush_range((unsigned long)(self->tx_buff.data), (unsigned long)(self->tx_buff.data+self->tx_buff.len)); set_dma_config(port->tx_dma_channel, set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8, DMA_SYNC_RESTART)); set_dma_start_addr(port->tx_dma_channel, (unsigned long)(self->tx_buff.data)); set_dma_x_count(port->tx_dma_channel, self->tx_buff.len); set_dma_x_modify(port->tx_dma_channel, 1); enable_dma(port->tx_dma_channel); }
static void bfin_sir_tx_chars(struct net_device *dev) { unsigned int chr; struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; if (self->tx_buff.len != 0) { chr = *(self->tx_buff.data); SIR_UART_PUT_CHAR(port, chr); self->tx_buff.data++; self->tx_buff.len--; } else { self->stats.tx_packets++; self->stats.tx_bytes += self->tx_buff.data - self->tx_buff.head; if (self->newspeed) { bfin_sir_set_speed(port, self->newspeed); self->speed = self->newspeed; self->newspeed = 0; } bfin_sir_stop_tx(port); bfin_sir_enable_rx(port); /* I'm hungry! */ netif_wake_queue(dev); } }
static int bfin_sir_open(struct net_device *dev) { struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; int err; self->newspeed = 0; self->speed = 9600; spin_lock_init(&self->lock); err = bfin_sir_startup(port, dev); if (err) goto err_startup; bfin_sir_set_speed(port, 9600); self->irlap = irlap_open(dev, &self->qos, DRIVER_NAME); if (!self->irlap) { err = -ENOMEM; goto err_irlap; } INIT_WORK(&self->work, bfin_sir_send_work); /* * Now enable the interrupt then start the queue */ self->open = 1; bfin_sir_enable_rx(port); netif_start_queue(dev); return 0; err_irlap: self->open = 0; bfin_sir_shutdown(port, dev); err_startup: return err; }
static int bfin_sir_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) { struct if_irda_req *rq = (struct if_irda_req *)ifreq; struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; int ret = 0; switch (cmd) { case SIOCSBANDWIDTH: if (capable(CAP_NET_ADMIN)) { if (self->open) { ret = bfin_sir_set_speed(port, rq->ifr_baudrate); bfin_sir_enable_rx(port); } else { dev_warn(&dev->dev, "SIOCSBANDWIDTH: !netif_running\n"); ret = 0; } } break; case SIOCSMEDIABUSY: ret = -EPERM; if (capable(CAP_NET_ADMIN)) { irda_device_set_media_busy(dev, TRUE); ret = 0; } break; case SIOCGRECEIVING: rq->ifr_receiving = bfin_sir_is_receiving(dev); break; default: ret = -EOPNOTSUPP; break; } return ret; }