static int pci200_close(struct net_device *dev) { sca_close(dev); sca_flush(dev_to_port(dev)->card); hdlc_close(dev); return 0; }
static int c101_open(struct net_device *dev) { port_t *port = dev_to_port(dev); int result; result = hdlc_open(dev); if (result) return result; writeb(1, port->win0base + C101_DTR); sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */ sca_open(dev); /* DCD is connected to port 2 !@#$%^& - disable MSCI0 CDCD interrupt */ sca_out(IE1_UDRN, MSCI0_OFFSET + IE1, port); sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port); set_carrier(port); /* enable MSCI1 CDCD interrupt */ sca_out(IE1_CDCD, MSCI1_OFFSET + IE1, port); sca_out(IE0_RXINTA, MSCI1_OFFSET + IE0, port); sca_out(0x48, IER0, port); /* TXINT #0 and RXINT #1 */ c101_set_iface(port); return 0; }
static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { const size_t size = sizeof(sync_serial_settings); sync_serial_settings new_line; sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS if (cmd == SIOCDEVPRIVATE) { sca_dump_rings(dev); printk(KERN_DEBUG "MSCI1: ST: %02x %02x %02x %02x\n", sca_in(MSCI1_OFFSET + ST0, port), sca_in(MSCI1_OFFSET + ST1, port), sca_in(MSCI1_OFFSET + ST2, port), sca_in(MSCI1_OFFSET + ST3, port)); return 0; } #endif if (cmd != SIOCWANDEV) return hdlc_ioctl(dev, ifr, cmd); switch(ifr->ifr_settings.type) { case IF_GET_IFACE: ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } if (copy_to_user(line, &port->settings, size)) return -EFAULT; return 0; case IF_IFACE_SYNC_SERIAL: if(!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&new_line, line, size)) return -EFAULT; if (new_line.clock_type != CLOCK_EXT && new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; memcpy(&port->settings, &new_line, size); /* Update settings */ c101_set_iface(port); return 0; default: return hdlc_ioctl(dev, ifr, cmd); } }
static int c101_close(struct net_device *dev) { port_t *port = dev_to_port(dev); sca_close(dev); writeb(0, port->win0base + C101_DTR); sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port); hdlc_close(dev); return 0; }
static void hss_hdlc_rx_irq(void *pdev) { struct net_device *dev = pdev; struct port *port = dev_to_port(dev); #if DEBUG_RX printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name); #endif qmgr_disable_irq(queue_ids[port->id].rx); napi_schedule(&port->napi); }
static int pc300_open(struct net_device *dev) { port_t *port = dev_to_port(dev); int result = hdlc_open(dev); if (result) return result; sca_open(dev); pc300_set_iface(port); return 0; }
static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { const size_t size = sizeof(sync_serial_settings); sync_serial_settings new_line; sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS if (cmd == SIOCDEVPRIVATE) { sca_dump_rings(dev); return 0; } #endif if (cmd != SIOCWANDEV) return hdlc_ioctl(dev, ifr, cmd); switch(ifr->ifr_settings.type) { case IF_GET_IFACE: ifr->ifr_settings.type = IF_IFACE_V35; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; return -ENOBUFS; } if (copy_to_user(line, &port->settings, size)) return -EFAULT; return 0; case IF_IFACE_V35: case IF_IFACE_SYNC_SERIAL: if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&new_line, line, size)) return -EFAULT; if (new_line.clock_type != CLOCK_EXT && new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) return -EINVAL; if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; memcpy(&port->settings, &new_line, size); pci200_set_iface(port); sca_flush(port->card); return 0; default: return hdlc_ioctl(dev, ifr, cmd); } }
static int n2_close(struct net_device *dev) { port_t *port = dev_to_port(dev); int io = port->card->io; u8 mcr = inb(io+N2_MCR) | (port->phy_node ? TX422_PORT1 : TX422_PORT0); sca_close(dev); mcr |= port->phy_node ? DTR_PORT1 : DTR_PORT0; /* set DTR OFF */ outb(mcr, io + N2_MCR); hdlc_close(dev); return 0; }
static int hss_hdlc_close(struct net_device *dev) { struct port *port = dev_to_port(dev); unsigned long flags; int i, buffs = RX_DESCS; spin_lock_irqsave(&npe_lock, flags); ports_open--; qmgr_disable_irq(queue_ids[port->id].rx); netif_stop_queue(dev); napi_disable(&port->napi); hss_stop_hdlc(port); while (queue_get_desc(queue_ids[port->id].rxfree, port, 0) >= 0) buffs--; while (queue_get_desc(queue_ids[port->id].rx, port, 0) >= 0) buffs--; if (buffs) netdev_crit(dev, "unable to drain RX queue, %i buffer(s) left in NPE\n", buffs); buffs = TX_DESCS; while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0) buffs--; i = 0; do { while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0) buffs--; if (!buffs) break; } while (++i < MAX_CLOSE_WAIT); if (buffs) netdev_crit(dev, "unable to drain TX queue, %i buffer(s) left in NPE\n", buffs); #if DEBUG_CLOSE if (!buffs) printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i); #endif qmgr_disable_irq(queue_ids[port->id].txdone); if (port->plat->close) port->plat->close(port->id, dev); spin_unlock_irqrestore(&npe_lock, flags); destroy_hdlc_queues(port); release_hdlc_queues(port); hdlc_close(dev); return 0; }
static void hss_hdlc_set_carrier(void *pdev, int carrier) { struct net_device *netdev = pdev; struct port *port = dev_to_port(netdev); unsigned long flags; spin_lock_irqsave(&npe_lock, flags); port->carrier = carrier; if (!port->loopback) { if (carrier) netif_carrier_on(netdev); else netif_carrier_off(netdev); } spin_unlock_irqrestore(&npe_lock, flags); }
static int n2_open(struct net_device *dev) { port_t *port = dev_to_port(dev); int io = port->card->io; u8 mcr = inb(io + N2_MCR) | (port->phy_node ? TX422_PORT1:TX422_PORT0); int result; result = hdlc_open(dev); if (result) return result; mcr &= port->phy_node ? ~DTR_PORT1 : ~DTR_PORT0; /* set DTR ON */ outb(mcr, io + N2_MCR); outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */ outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */ sca_open(dev); n2_set_iface(port); return 0; }
static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding, unsigned short parity) { struct port *port = dev_to_port(dev); if (encoding != ENCODING_NRZ) return -EINVAL; switch(parity) { case PARITY_CRC16_PR1_CCITT: port->hdlc_cfg = 0; return 0; case PARITY_CRC32_PR1_CCITT: port->hdlc_cfg = PKT_HDLC_CRC_32; return 0; default: return -EINVAL; } }
static void hss_hdlc_txdone_irq(void *pdev) { struct net_device *dev = pdev; struct port *port = dev_to_port(dev); int n_desc; #if DEBUG_TX printk(KERN_DEBUG DRV_NAME ": hss_hdlc_txdone_irq\n"); #endif while ((n_desc = queue_get_desc(queue_ids[port->id].txdone, port, 1)) >= 0) { struct desc *desc; int start; desc = tx_desc_ptr(port, n_desc); dev->stats.tx_packets++; dev->stats.tx_bytes += desc->pkt_len; dma_unmap_tx(port, desc); #if DEBUG_TX printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq free %p\n", dev->name, port->tx_buff_tab[n_desc]); #endif free_buffer_irq(port->tx_buff_tab[n_desc]); port->tx_buff_tab[n_desc] = NULL; start = qmgr_stat_below_low_watermark(port->plat->txreadyq); queue_put_desc(port->plat->txreadyq, tx_desc_phys(port, n_desc), desc); if (start) { #if DEBUG_TX printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" " ready\n", dev->name); #endif netif_wake_queue(dev); } } }
static io_return_t device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type, dev_mode_t mode, char *name, device_t *devp) { io_return_t err = D_SUCCESS; ipc_port_t notify; struct ifnet *ifp; struct linux_device *dev; struct net_data *nd; /* Search for the device. */ for (dev = dev_base; dev; dev = dev->next) if (dev->base_addr && dev->base_addr != 0xffe0 && !strcmp (name, dev->name)) break; if (!dev) return D_NO_SUCH_DEVICE; /* Allocate and initialize device data if this is the first open. */ nd = dev->net_data; if (!nd) { dev->net_data = nd = ((struct net_data *) kalloc (sizeof (struct net_data))); if (!nd) { err = D_NO_MEMORY; goto out; } nd->dev = dev; nd->device.emul_data = nd; nd->device.emul_ops = &linux_net_emulation_ops; nd->port = ipc_port_alloc_kernel (); if (nd->port == IP_NULL) { err = KERN_RESOURCE_SHORTAGE; goto out; } ipc_kobject_set (nd->port, (ipc_kobject_t) & nd->device, IKOT_DEVICE); notify = ipc_port_make_sonce (nd->port); ip_lock (nd->port); ipc_port_nsrequest (nd->port, 1, notify, ¬ify); assert (notify == IP_NULL); ifp = &nd->ifnet; ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0'; ifp->if_flags = IFF_UP | IFF_RUNNING; ifp->if_mtu = dev->mtu; ifp->if_header_size = dev->hard_header_len; ifp->if_header_format = dev->type; ifp->if_address_size = dev->addr_len; ifp->if_address = dev->dev_addr; if_init_queues (ifp); if (dev->open) { linux_intr_pri = SPL6; if ((*dev->open) (dev)) err = D_NO_SUCH_DEVICE; } out: if (err) { if (nd) { if (nd->port != IP_NULL) { ipc_kobject_set (nd->port, IKO_NULL, IKOT_NONE); ipc_port_dealloc_kernel (nd->port); } kfree ((vm_offset_t) nd, sizeof (struct net_data)); nd = NULL; dev->net_data = NULL; } } else { /* IPv6 heavily relies on multicasting (especially router and neighbor solicits and advertisements), so enable reception of those multicast packets by setting `LINUX_IFF_ALLMULTI'. */ dev->flags |= LINUX_IFF_UP | LINUX_IFF_RUNNING | LINUX_IFF_ALLMULTI; skb_queue_head_init (&dev->buffs[0]); if (dev->set_multicast_list) dev->set_multicast_list (dev); } if (IP_VALID (reply_port)) ds_device_open_reply (reply_port, reply_port_type, err, dev_to_port (nd)); return MIG_NO_REPLY; } *devp = &nd->device; return D_SUCCESS; }
static int hss_hdlc_open(struct net_device *dev) { struct port *port = dev_to_port(dev); unsigned long flags; int i, err = 0; if ((err = hdlc_open(dev))) return err; if ((err = hss_load_firmware(port))) goto err_hdlc_close; if ((err = request_hdlc_queues(port))) goto err_hdlc_close; if ((err = init_hdlc_queues(port))) goto err_destroy_queues; spin_lock_irqsave(&npe_lock, flags); if (port->plat->open) if ((err = port->plat->open(port->id, dev, hss_hdlc_set_carrier))) goto err_unlock; spin_unlock_irqrestore(&npe_lock, flags); for (i = 0; i < TX_DESCS; i++) queue_put_desc(port->plat->txreadyq, tx_desc_phys(port, i), tx_desc_ptr(port, i)); for (i = 0; i < RX_DESCS; i++) queue_put_desc(queue_ids[port->id].rxfree, rx_desc_phys(port, i), rx_desc_ptr(port, i)); napi_enable(&port->napi); netif_start_queue(dev); qmgr_set_irq(queue_ids[port->id].rx, QUEUE_IRQ_SRC_NOT_EMPTY, hss_hdlc_rx_irq, dev); qmgr_set_irq(queue_ids[port->id].txdone, QUEUE_IRQ_SRC_NOT_EMPTY, hss_hdlc_txdone_irq, dev); qmgr_enable_irq(queue_ids[port->id].txdone); ports_open++; hss_set_hdlc_cfg(port); hss_config(port); hss_start_hdlc(port); napi_schedule(&port->napi); return 0; err_unlock: spin_unlock_irqrestore(&npe_lock, flags); err_destroy_queues: destroy_hdlc_queues(port); release_hdlc_queues(port); err_hdlc_close: hdlc_close(dev); return err; }
static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) { struct port *port = dev_to_port(dev); unsigned int txreadyq = port->plat->txreadyq; int len, offset, bytes, n; void *mem; u32 phys; struct desc *desc; #if DEBUG_TX printk(KERN_DEBUG "%s: hss_hdlc_xmit\n", dev->name); #endif if (unlikely(skb->len > HDLC_MAX_MRU)) { dev_kfree_skb(skb); dev->stats.tx_errors++; return NETDEV_TX_OK; } debug_pkt(dev, "hss_hdlc_xmit", skb->data, skb->len); len = skb->len; #ifdef __ARMEB__ offset = 0; bytes = len; mem = skb->data; #else offset = (int)skb->data & 3; bytes = ALIGN(offset + len, 4); if (!(mem = kmalloc(bytes, GFP_ATOMIC))) { dev_kfree_skb(skb); dev->stats.tx_dropped++; return NETDEV_TX_OK; } memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); dev_kfree_skb(skb); #endif phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); if (dma_mapping_error(&dev->dev, phys)) { #ifdef __ARMEB__ dev_kfree_skb(skb); #else kfree(mem); #endif dev->stats.tx_dropped++; return NETDEV_TX_OK; } n = queue_get_desc(txreadyq, port, 1); BUG_ON(n < 0); desc = tx_desc_ptr(port, n); #ifdef __ARMEB__ port->tx_buff_tab[n] = skb; #else port->tx_buff_tab[n] = mem; #endif desc->data = phys + offset; desc->buf_len = desc->pkt_len = len; wmb(); queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); if (qmgr_stat_below_low_watermark(txreadyq)) { #if DEBUG_TX printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); #endif netif_stop_queue(dev); if (!qmgr_stat_below_low_watermark(txreadyq)) { #if DEBUG_TX printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", dev->name); #endif netif_wake_queue(dev); } } #if DEBUG_TX printk(KERN_DEBUG "%s: hss_hdlc_xmit end\n", dev->name); #endif return NETDEV_TX_OK; }
static int pc300_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { const size_t size = sizeof(sync_serial_settings); sync_serial_settings new_line; sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; int new_type; port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS if (cmd == SIOCDEVPRIVATE) { sca_dump_rings(dev); return 0; } #endif if (cmd != SIOCWANDEV) return hdlc_ioctl(dev, ifr, cmd); if (ifr->ifr_settings.type == IF_GET_IFACE) { ifr->ifr_settings.type = port->iface; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } if (copy_to_user(line, &port->settings, size)) return -EFAULT; return 0; } if (port->card->type == PC300_X21 && (ifr->ifr_settings.type == IF_IFACE_SYNC_SERIAL || ifr->ifr_settings.type == IF_IFACE_X21)) new_type = IF_IFACE_X21; else if (port->card->type == PC300_RSV && (ifr->ifr_settings.type == IF_IFACE_SYNC_SERIAL || ifr->ifr_settings.type == IF_IFACE_V35)) new_type = IF_IFACE_V35; else if (port->card->type == PC300_RSV && ifr->ifr_settings.type == IF_IFACE_V24) new_type = IF_IFACE_V24; else return hdlc_ioctl(dev, ifr, cmd); if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&new_line, line, size)) return -EFAULT; if (new_line.clock_type != CLOCK_EXT && new_line.clock_type != CLOCK_TXFROMRX && new_line.clock_type != CLOCK_INT && new_line.clock_type != CLOCK_TXINT) return -EINVAL; /* No such clock setting */ if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; memcpy(&port->settings, &new_line, size); /* Update settings */ port->iface = new_type; pc300_set_iface(port); return 0; }
static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { const size_t size = sizeof(sync_serial_settings); sync_serial_settings new_line; sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; struct port *port = dev_to_port(dev); unsigned long flags; int clk; if (cmd != SIOCWANDEV) return hdlc_ioctl(dev, ifr, cmd); switch(ifr->ifr_settings.type) { case IF_GET_IFACE: ifr->ifr_settings.type = IF_IFACE_V35; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; return -ENOBUFS; } memset(&new_line, 0, sizeof(new_line)); new_line.clock_type = port->clock_type; new_line.clock_rate = port->clock_rate; new_line.loopback = port->loopback; if (copy_to_user(line, &new_line, size)) return -EFAULT; return 0; case IF_IFACE_SYNC_SERIAL: case IF_IFACE_V35: if(!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&new_line, line, size)) return -EFAULT; clk = new_line.clock_type; if (port->plat->set_clock) clk = port->plat->set_clock(port->id, clk); if (clk != CLOCK_EXT && clk != CLOCK_INT) return -EINVAL; if (new_line.loopback != 0 && new_line.loopback != 1) return -EINVAL; port->clock_type = clk; if (clk == CLOCK_INT) find_best_clock(new_line.clock_rate, &port->clock_rate, &port->clock_reg); else { port->clock_rate = 0; port->clock_reg = CLK42X_SPEED_2048KHZ; } port->loopback = new_line.loopback; spin_lock_irqsave(&npe_lock, flags); if (dev->flags & IFF_UP) hss_config(port); if (port->loopback || port->carrier) netif_carrier_on(port->netdev); else netif_carrier_off(port->netdev); spin_unlock_irqrestore(&npe_lock, flags); return 0; default: return hdlc_ioctl(dev, ifr, cmd); } }