| /* Copyright (C) 2003-2005 SBE, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| |
| #include <linux/slab.h> |
| #include <linux/io.h> |
| #include <asm/byteorder.h> |
| #include <linux/netdevice.h> |
| #include <linux/delay.h> |
| #include <linux/hdlc.h> |
| #include "pmcc4_sysdep.h" |
| #include "sbecom_inline_linux.h" |
| #include "libsbew.h" |
| #include "pmcc4.h" |
| |
| |
| #ifndef USE_MAX_INT_DELAY |
| static int dummy = 0; |
| |
| #endif |
| |
| extern int drvr_state; |
| |
| |
| #if 1 |
| u_int32_t |
| pci_read_32(u_int32_t *p) |
| { |
| #ifdef FLOW_DEBUG |
| u_int32_t v; |
| |
| FLUSH_PCI_READ(); |
| v = le32_to_cpu(*p); |
| if (cxt1e1_log_level >= LOG_DEBUG) |
| pr_info("pci_read : %x = %x\n", (u_int32_t) p, v); |
| return v; |
| #else |
| FLUSH_PCI_READ(); /* */ |
| return le32_to_cpu(*p); |
| #endif |
| } |
| |
| void |
| pci_write_32(u_int32_t *p, u_int32_t v) |
| { |
| #ifdef FLOW_DEBUG |
| if (cxt1e1_log_level >= LOG_DEBUG) |
| pr_info("pci_write: %x = %x\n", (u_int32_t) p, v); |
| #endif |
| *p = cpu_to_le32 (v); |
| FLUSH_PCI_WRITE(); /* This routine is called from routines |
| * which do multiple register writes |
| * which themselves need flushing between |
| * writes in order to guarantee write |
| * ordering. It is less code-cumbersome |
| * to flush here-in then to investigate |
| * and code the many other register |
| * writing routines. */ |
| } |
| #endif |
| |
| |
| void |
| pci_flush_write(ci_t *ci) |
| { |
| volatile u_int32_t v; |
| |
| /* issue a PCI read to flush PCI write thru bridge */ |
| v = *(u_int32_t *) &ci->reg->glcd; /* any address would do */ |
| |
| /* |
| * return nothing, this just reads PCI bridge interface to flush |
| * previously written data |
| */ |
| } |
| |
| |
| static void |
| watchdog_func(unsigned long arg) |
| { |
| struct watchdog *wd = (void *) arg; |
| |
| if (drvr_state != SBE_DRVR_AVAILABLE) { |
| if (cxt1e1_log_level >= LOG_MONITOR) |
| pr_warning("%s: drvr not available (%x)\n", |
| __func__, drvr_state); |
| return; |
| } |
| schedule_work(&wd->work); |
| mod_timer(&wd->h, jiffies + wd->ticks); |
| } |
| |
| int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), |
| void *c, int usec) |
| { |
| wdp->func = f; |
| wdp->softc = c; |
| wdp->ticks = (HZ) * (usec / 1000) / 1000; |
| INIT_WORK(&wdp->work, (void *)f); |
| init_timer(&wdp->h); |
| { |
| ci_t *ci = (ci_t *) c; |
| |
| wdp->h.data = (unsigned long) &ci->wd; |
| } |
| wdp->h.function = watchdog_func; |
| return 0; |
| } |
| |
| void |
| OS_uwait(int usec, char *description) |
| { |
| int tmp; |
| |
| if (usec >= 1000) { |
| mdelay(usec / 1000); |
| /* now delay residual */ |
| tmp = (usec / 1000) * 1000; /* round */ |
| tmp = usec - tmp; /* residual */ |
| if (tmp) { /* wait on residual */ |
| udelay(tmp); |
| } |
| } else { |
| udelay(usec); |
| } |
| } |
| |
| /* dummy short delay routine called as a subroutine so that compiler |
| * does not optimize/remove its intent (a short delay) |
| */ |
| |
| void |
| OS_uwait_dummy(void) |
| { |
| #ifndef USE_MAX_INT_DELAY |
| dummy++; |
| #else |
| udelay(1); |
| #endif |
| } |
| |
| |
| void |
| OS_sem_init(void *sem, int state) |
| { |
| switch (state) { |
| case SEM_TAKEN: |
| sema_init((struct semaphore *) sem, 0); |
| break; |
| case SEM_AVAILABLE: |
| sema_init((struct semaphore *) sem, 1); |
| break; |
| default: /* otherwise, set sem.count to state's |
| * value */ |
| sema_init(sem, state); |
| break; |
| } |
| } |
| |
| |
| int |
| sd_line_is_ok(void *user) |
| { |
| struct net_device *ndev = (struct net_device *) user; |
| |
| return netif_carrier_ok(ndev); |
| } |
| |
| void |
| sd_line_is_up(void *user) |
| { |
| struct net_device *ndev = (struct net_device *) user; |
| |
| netif_carrier_on(ndev); |
| return; |
| } |
| |
| void |
| sd_line_is_down(void *user) |
| { |
| struct net_device *ndev = (struct net_device *) user; |
| |
| netif_carrier_off(ndev); |
| return; |
| } |
| |
| void |
| sd_disable_xmit(void *user) |
| { |
| struct net_device *dev = (struct net_device *) user; |
| |
| netif_stop_queue(dev); |
| return; |
| } |
| |
| void |
| sd_enable_xmit(void *user) |
| { |
| struct net_device *dev = (struct net_device *) user; |
| |
| netif_wake_queue(dev); |
| return; |
| } |
| |
| int |
| sd_queue_stopped(void *user) |
| { |
| struct net_device *ndev = (struct net_device *) user; |
| |
| return netif_queue_stopped(ndev); |
| } |
| |
| void sd_recv_consume(void *token, size_t len, void *user) |
| { |
| struct net_device *ndev = user; |
| struct sk_buff *skb = token; |
| |
| skb->dev = ndev; |
| skb_put(skb, len); |
| skb->protocol = hdlc_type_trans(skb, ndev); |
| netif_rx(skb); |
| } |
| |
| |
| /** |
| ** Read some reserved location w/in the COMET chip as a usable |
| ** VMETRO trigger point or other trace marking event. |
| **/ |
| |
| #include "comet.h" |
| |
| extern ci_t *CI; /* dummy pointer to board ZERO's data */ |
| void |
| VMETRO_TRIGGER(ci_t *ci, int x) |
| { |
| struct s_comet_reg *comet; |
| volatile u_int32_t data; |
| |
| comet = ci->port[0].cometbase; /* default to COMET # 0 */ |
| |
| switch (x) { |
| default: |
| case 0: |
| data = pci_read_32((u_int32_t *) &comet->__res24); /* 0x90 */ |
| break; |
| case 1: |
| data = pci_read_32((u_int32_t *) &comet->__res25); /* 0x94 */ |
| break; |
| case 2: |
| data = pci_read_32((u_int32_t *) &comet->__res26); /* 0x98 */ |
| break; |
| case 3: |
| data = pci_read_32((u_int32_t *) &comet->__res27); /* 0x9C */ |
| break; |
| case 4: |
| data = pci_read_32((u_int32_t *) &comet->__res88); /* 0x220 */ |
| break; |
| case 5: |
| data = pci_read_32((u_int32_t *) &comet->__res89); /* 0x224 */ |
| break; |
| case 6: |
| data = pci_read_32((u_int32_t *) &comet->__res8A); /* 0x228 */ |
| break; |
| case 7: |
| data = pci_read_32((u_int32_t *) &comet->__res8B); /* 0x22C */ |
| break; |
| case 8: |
| data = pci_read_32((u_int32_t *) &comet->__resA0); /* 0x280 */ |
| break; |
| case 9: |
| data = pci_read_32((u_int32_t *) &comet->__resA1); /* 0x284 */ |
| break; |
| case 10: |
| data = pci_read_32((u_int32_t *) &comet->__resA2); /* 0x288 */ |
| break; |
| case 11: |
| data = pci_read_32((u_int32_t *) &comet->__resA3); /* 0x28C */ |
| break; |
| case 12: |
| data = pci_read_32((u_int32_t *) &comet->__resA4); /* 0x290 */ |
| break; |
| case 13: |
| data = pci_read_32((u_int32_t *) &comet->__resA5); /* 0x294 */ |
| break; |
| case 14: |
| data = pci_read_32((u_int32_t *) &comet->__resA6); /* 0x298 */ |
| break; |
| case 15: |
| data = pci_read_32((u_int32_t *) &comet->__resA7); /* 0x29C */ |
| break; |
| case 16: |
| data = pci_read_32((u_int32_t *) &comet->__res74); /* 0x1D0 */ |
| break; |
| case 17: |
| data = pci_read_32((u_int32_t *) &comet->__res75); /* 0x1D4 */ |
| break; |
| case 18: |
| data = pci_read_32((u_int32_t *) &comet->__res76); /* 0x1D8 */ |
| break; |
| case 19: |
| data = pci_read_32((u_int32_t *) &comet->__res77); /* 0x1DC */ |
| break; |
| } |
| } |
| |
| |
| /*** End-of-File ***/ |