1/* Copyright (C) 2003-2005 SBE, Inc. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 16#include <linux/slab.h> 17#include <asm/io.h> 18#include <asm/byteorder.h> 19#include <linux/netdevice.h> 20#include <linux/delay.h> 21#include <linux/hdlc.h> 22#include "pmcc4_sysdep.h" 23#include "sbecom_inline_linux.h" 24#include "libsbew.h" 25#include "pmcc4.h" 26 27 28#ifdef SBE_INCLUDE_SYMBOLS 29#define STATIC 30#else 31#define STATIC static 32#endif 33 34#if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \ 35 defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE) 36#define _v7_hdlc_ 1 37#else 38#define _v7_hdlc_ 0 39#endif 40 41#if _v7_hdlc_ 42#define V7(x) (x ## _v7) 43extern int hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *); 44extern int register_hdlc_device_v7 (hdlc_device *); 45extern int unregister_hdlc_device_v7 (hdlc_device *); 46 47#else 48#define V7(x) x 49#endif 50 51 52#ifndef USE_MAX_INT_DELAY 53static int dummy = 0; 54 55#endif 56 57extern int log_level; 58extern int drvr_state; 59 60 61u_int32_t 62pci_read_32 (u_int32_t *p) 63{ 64#ifdef FLOW_DEBUG 65 u_int32_t v; 66 67 FLUSH_PCI_READ (); 68 v = le32_to_cpu (*p); 69 if (log_level >= LOG_DEBUG) 70 pr_info("pci_read : %x = %x\n", (u_int32_t) p, v); 71 return v; 72#else 73 FLUSH_PCI_READ (); /* */ 74 return le32_to_cpu (*p); 75#endif 76} 77 78void 79pci_write_32 (u_int32_t *p, u_int32_t v) 80{ 81#ifdef FLOW_DEBUG 82 if (log_level >= LOG_DEBUG) 83 pr_info("pci_write: %x = %x\n", (u_int32_t) p, v); 84#endif 85 *p = cpu_to_le32 (v); 86 FLUSH_PCI_WRITE (); /* This routine is called from routines 87 * which do multiple register writes 88 * which themselves need flushing between 89 * writes in order to guarantee write 90 * ordering. It is less code-cumbersome 91 * to flush here-in then to investigate 92 * and code the many other register 93 * writing routines. */ 94} 95 96 97void 98pci_flush_write (ci_t * ci) 99{ 100 volatile u_int32_t v; 101 102 /* issue a PCI read to flush PCI write thru bridge */ 103 v = *(u_int32_t *) &ci->reg->glcd; /* any address would do */ 104 105 /* 106 * return nothing, this just reads PCI bridge interface to flush 107 * previously written data 108 */ 109} 110 111 112STATIC void 113watchdog_func (unsigned long arg) 114{ 115 struct watchdog *wd = (void *) arg; 116 117 if (drvr_state != SBE_DRVR_AVAILABLE) 118 { 119 if (log_level >= LOG_MONITOR) 120 pr_warning("%s: drvr not available (%x)\n", __func__, drvr_state); 121 return; 122 } 123 schedule_work (&wd->work); 124 mod_timer (&wd->h, jiffies + wd->ticks); 125} 126 127int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *c, int usec) 128{ 129 wdp->func = f; 130 wdp->softc = c; 131 wdp->ticks = (HZ) * (usec / 1000) / 1000; 132 INIT_WORK(&wdp->work, (void *)f); 133 init_timer (&wdp->h); 134 { 135 ci_t *ci = (ci_t *) c; 136 137 wdp->h.data = (unsigned long) &ci->wd; 138 } 139 wdp->h.function = watchdog_func; 140 return 0; 141} 142 143void 144OS_uwait (int usec, char *description) 145{ 146 int tmp; 147 148 if (usec >= 1000) 149 { 150 mdelay (usec / 1000); 151 /* now delay residual */ 152 tmp = (usec / 1000) * 1000; /* round */ 153 tmp = usec - tmp; /* residual */ 154 if (tmp) 155 { /* wait on residual */ 156 udelay (tmp); 157 } 158 } else 159 { 160 udelay (usec); 161 } 162} 163 164/* dummy short delay routine called as a subroutine so that compiler 165 * does not optimize/remove its intent (a short delay) 166 */ 167 168void 169OS_uwait_dummy (void) 170{ 171#ifndef USE_MAX_INT_DELAY 172 dummy++; 173#else 174 udelay (1); 175#endif 176} 177 178 179void 180OS_sem_init (void *sem, int state) 181{ 182 switch (state) 183 { 184 case SEM_TAKEN: 185 init_MUTEX_LOCKED ((struct semaphore *) sem); 186 break; 187 case SEM_AVAILABLE: 188 init_MUTEX ((struct semaphore *) sem); 189 break; 190 default: /* otherwise, set sem.count to state's 191 * value */ 192 sema_init (sem, state); 193 break; 194 } 195} 196 197 198int 199sd_line_is_ok (void *user) 200{ 201 struct net_device *ndev = (struct net_device *) user; 202 203 return (netif_carrier_ok (ndev)); 204} 205 206void 207sd_line_is_up (void *user) 208{ 209 struct net_device *ndev = (struct net_device *) user; 210 211 netif_carrier_on (ndev); 212 return; 213} 214 215void 216sd_line_is_down (void *user) 217{ 218 struct net_device *ndev = (struct net_device *) user; 219 220 netif_carrier_off (ndev); 221 return; 222} 223 224void 225sd_disable_xmit (void *user) 226{ 227 struct net_device *dev = (struct net_device *) user; 228 229 netif_stop_queue (dev); 230 return; 231} 232 233void 234sd_enable_xmit (void *user) 235{ 236 struct net_device *dev = (struct net_device *) user; 237 238 netif_wake_queue (dev); 239 return; 240} 241 242int 243sd_queue_stopped (void *user) 244{ 245 struct net_device *ndev = (struct net_device *) user; 246 247 return (netif_queue_stopped (ndev)); 248} 249 250void sd_recv_consume(void *token, size_t len, void *user) 251{ 252 struct net_device *ndev = user; 253 struct sk_buff *skb = token; 254 255 skb->dev = ndev; 256 skb_put (skb, len); 257 skb->protocol = hdlc_type_trans(skb, ndev); 258 netif_rx(skb); 259} 260 261 262/** 263 ** Read some reserved location w/in the COMET chip as a usable 264 ** VMETRO trigger point or other trace marking event. 265 **/ 266 267#include "comet.h" 268 269extern ci_t *CI; /* dummy pointer to board ZERO's data */ 270void 271VMETRO_TRACE (void *x) 272{ 273 u_int32_t y = (u_int32_t) x; 274 275 pci_write_32 ((u_int32_t *) &CI->cpldbase->leds, y); 276} 277 278 279void 280VMETRO_TRIGGER (ci_t * ci, int x) 281{ 282 comet_t *comet; 283 volatile u_int32_t data; 284 285 comet = ci->port[0].cometbase; /* default to COMET # 0 */ 286 287 switch (x) 288 { 289 default: 290 case 0: 291 data = pci_read_32 ((u_int32_t *) &comet->__res24); /* 0x90 */ 292 break; 293 case 1: 294 data = pci_read_32 ((u_int32_t *) &comet->__res25); /* 0x94 */ 295 break; 296 case 2: 297 data = pci_read_32 ((u_int32_t *) &comet->__res26); /* 0x98 */ 298 break; 299 case 3: 300 data = pci_read_32 ((u_int32_t *) &comet->__res27); /* 0x9C */ 301 break; 302 case 4: 303 data = pci_read_32 ((u_int32_t *) &comet->__res88); /* 0x220 */ 304 break; 305 case 5: 306 data = pci_read_32 ((u_int32_t *) &comet->__res89); /* 0x224 */ 307 break; 308 case 6: 309 data = pci_read_32 ((u_int32_t *) &comet->__res8A); /* 0x228 */ 310 break; 311 case 7: 312 data = pci_read_32 ((u_int32_t *) &comet->__res8B); /* 0x22C */ 313 break; 314 case 8: 315 data = pci_read_32 ((u_int32_t *) &comet->__resA0); /* 0x280 */ 316 break; 317 case 9: 318 data = pci_read_32 ((u_int32_t *) &comet->__resA1); /* 0x284 */ 319 break; 320 case 10: 321 data = pci_read_32 ((u_int32_t *) &comet->__resA2); /* 0x288 */ 322 break; 323 case 11: 324 data = pci_read_32 ((u_int32_t *) &comet->__resA3); /* 0x28C */ 325 break; 326 case 12: 327 data = pci_read_32 ((u_int32_t *) &comet->__resA4); /* 0x290 */ 328 break; 329 case 13: 330 data = pci_read_32 ((u_int32_t *) &comet->__resA5); /* 0x294 */ 331 break; 332 case 14: 333 data = pci_read_32 ((u_int32_t *) &comet->__resA6); /* 0x298 */ 334 break; 335 case 15: 336 data = pci_read_32 ((u_int32_t *) &comet->__resA7); /* 0x29C */ 337 break; 338 case 16: 339 data = pci_read_32 ((u_int32_t *) &comet->__res74); /* 0x1D0 */ 340 break; 341 case 17: 342 data = pci_read_32 ((u_int32_t *) &comet->__res75); /* 0x1D4 */ 343 break; 344 case 18: 345 data = pci_read_32 ((u_int32_t *) &comet->__res76); /* 0x1D8 */ 346 break; 347 case 19: 348 data = pci_read_32 ((u_int32_t *) &comet->__res77); /* 0x1DC */ 349 break; 350 } 351} 352 353 354/*** End-of-File ***/ 355