| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /****************************************************************************** | 
 | 2 |  * | 
 | 3 |  * nicstar.c | 
 | 4 |  * | 
 | 5 |  * Device driver supporting CBR for IDT 77201/77211 "NICStAR" based cards. | 
 | 6 |  * | 
 | 7 |  * IMPORTANT: The included file nicstarmac.c was NOT WRITTEN BY ME. | 
 | 8 |  *            It was taken from the frle-0.22 device driver. | 
 | 9 |  *            As the file doesn't have a copyright notice, in the file | 
 | 10 |  *            nicstarmac.copyright I put the copyright notice from the | 
 | 11 |  *            frle-0.22 device driver. | 
 | 12 |  *            Some code is based on the nicstar driver by M. Welsh. | 
 | 13 |  * | 
 | 14 |  * Author: Rui Prior (rprior@inescn.pt) | 
 | 15 |  * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999 | 
 | 16 |  * | 
 | 17 |  * | 
 | 18 |  * (C) INESC 1999 | 
 | 19 |  * | 
 | 20 |  * | 
 | 21 |  ******************************************************************************/ | 
 | 22 |  | 
 | 23 |  | 
 | 24 | /**** IMPORTANT INFORMATION *************************************************** | 
 | 25 |  * | 
 | 26 |  * There are currently three types of spinlocks: | 
 | 27 |  * | 
 | 28 |  * 1 - Per card interrupt spinlock (to protect structures and such) | 
 | 29 |  * 2 - Per SCQ scq spinlock | 
 | 30 |  * 3 - Per card resource spinlock (to access registers, etc.) | 
 | 31 |  * | 
 | 32 |  * These must NEVER be grabbed in reverse order. | 
 | 33 |  * | 
 | 34 |  ******************************************************************************/ | 
 | 35 |  | 
 | 36 | /* Header files ***************************************************************/ | 
 | 37 |  | 
 | 38 | #include <linux/module.h> | 
 | 39 | #include <linux/config.h> | 
 | 40 | #include <linux/kernel.h> | 
 | 41 | #include <linux/skbuff.h> | 
 | 42 | #include <linux/atmdev.h> | 
 | 43 | #include <linux/atm.h> | 
 | 44 | #include <linux/pci.h> | 
 | 45 | #include <linux/types.h> | 
 | 46 | #include <linux/string.h> | 
 | 47 | #include <linux/delay.h> | 
 | 48 | #include <linux/init.h> | 
 | 49 | #include <linux/sched.h> | 
 | 50 | #include <linux/timer.h> | 
 | 51 | #include <linux/interrupt.h> | 
 | 52 | #include <linux/bitops.h> | 
 | 53 | #include <asm/io.h> | 
 | 54 | #include <asm/uaccess.h> | 
 | 55 | #include <asm/atomic.h> | 
 | 56 | #include "nicstar.h" | 
 | 57 | #ifdef CONFIG_ATM_NICSTAR_USE_SUNI | 
 | 58 | #include "suni.h" | 
 | 59 | #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ | 
 | 60 | #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105 | 
 | 61 | #include "idt77105.h" | 
 | 62 | #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ | 
 | 63 |  | 
 | 64 | #if BITS_PER_LONG != 32 | 
 | 65 | #  error FIXME: this driver requires a 32-bit platform | 
 | 66 | #endif | 
 | 67 |  | 
 | 68 | /* Additional code ************************************************************/ | 
 | 69 |  | 
 | 70 | #include "nicstarmac.c" | 
 | 71 |  | 
 | 72 |  | 
 | 73 | /* Configurable parameters ****************************************************/ | 
 | 74 |  | 
 | 75 | #undef PHY_LOOPBACK | 
 | 76 | #undef TX_DEBUG | 
 | 77 | #undef RX_DEBUG | 
 | 78 | #undef GENERAL_DEBUG | 
 | 79 | #undef EXTRA_DEBUG | 
 | 80 |  | 
 | 81 | #undef NS_USE_DESTRUCTORS /* For now keep this undefined unless you know | 
 | 82 |                              you're going to use only raw ATM */ | 
 | 83 |  | 
 | 84 |  | 
 | 85 | /* Do not touch these *********************************************************/ | 
 | 86 |  | 
 | 87 | #ifdef TX_DEBUG | 
 | 88 | #define TXPRINTK(args...) printk(args) | 
 | 89 | #else | 
 | 90 | #define TXPRINTK(args...) | 
 | 91 | #endif /* TX_DEBUG */ | 
 | 92 |  | 
 | 93 | #ifdef RX_DEBUG | 
 | 94 | #define RXPRINTK(args...) printk(args) | 
 | 95 | #else | 
 | 96 | #define RXPRINTK(args...) | 
 | 97 | #endif /* RX_DEBUG */ | 
 | 98 |  | 
 | 99 | #ifdef GENERAL_DEBUG | 
 | 100 | #define PRINTK(args...) printk(args) | 
 | 101 | #else | 
 | 102 | #define PRINTK(args...) | 
 | 103 | #endif /* GENERAL_DEBUG */ | 
 | 104 |  | 
 | 105 | #ifdef EXTRA_DEBUG | 
 | 106 | #define XPRINTK(args...) printk(args) | 
 | 107 | #else | 
 | 108 | #define XPRINTK(args...) | 
 | 109 | #endif /* EXTRA_DEBUG */ | 
 | 110 |  | 
 | 111 |  | 
 | 112 | /* Macros *********************************************************************/ | 
 | 113 |  | 
 | 114 | #define CMD_BUSY(card) (readl((card)->membase + STAT) & NS_STAT_CMDBZ) | 
 | 115 |  | 
 | 116 | #define NS_DELAY mdelay(1) | 
 | 117 |  | 
 | 118 | #define ALIGN_BUS_ADDR(addr, alignment) \ | 
 | 119 |         ((((u32) (addr)) + (((u32) (alignment)) - 1)) & ~(((u32) (alignment)) - 1)) | 
 | 120 | #define ALIGN_ADDRESS(addr, alignment) \ | 
 | 121 |         bus_to_virt(ALIGN_BUS_ADDR(virt_to_bus(addr), alignment)) | 
 | 122 |  | 
 | 123 | #undef CEIL | 
 | 124 |  | 
 | 125 | #ifndef ATM_SKB | 
 | 126 | #define ATM_SKB(s) (&(s)->atm) | 
 | 127 | #endif | 
 | 128 |  | 
 | 129 |    /* Spinlock debugging stuff */ | 
 | 130 | #ifdef NS_DEBUG_SPINLOCKS /* See nicstar.h */ | 
 | 131 | #define ns_grab_int_lock(card,flags) \ | 
 | 132 |  do { \ | 
 | 133 |     unsigned long nsdsf, nsdsf2; \ | 
 | 134 |     local_irq_save(flags); \ | 
 | 135 |     save_flags(nsdsf); cli();\ | 
 | 136 |     if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ | 
 | 137 |                                 (flags)&(1<<9)?"en":"dis"); \ | 
 | 138 |     if (spin_is_locked(&(card)->int_lock) && \ | 
 | 139 |         (card)->cpu_int == smp_processor_id()) { \ | 
 | 140 |        printk("nicstar.c: line %d (cpu %d) int_lock already locked at line %d (cpu %d)\n", \ | 
 | 141 |               __LINE__, smp_processor_id(), (card)->has_int_lock, \ | 
 | 142 |               (card)->cpu_int); \ | 
 | 143 |        printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | 
 | 144 |     } \ | 
 | 145 |     if (spin_is_locked(&(card)->res_lock) && \ | 
 | 146 |         (card)->cpu_res == smp_processor_id()) { \ | 
 | 147 |        printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying int)\n", \ | 
 | 148 |               __LINE__, smp_processor_id(), (card)->has_res_lock, \ | 
 | 149 |               (card)->cpu_res); \ | 
 | 150 |        printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | 
 | 151 |     } \ | 
 | 152 |     spin_lock_irq(&(card)->int_lock); \ | 
 | 153 |     (card)->has_int_lock = __LINE__; \ | 
 | 154 |     (card)->cpu_int = smp_processor_id(); \ | 
 | 155 |     restore_flags(nsdsf); } while (0) | 
 | 156 | #define ns_grab_res_lock(card,flags) \ | 
 | 157 |  do { \ | 
 | 158 |     unsigned long nsdsf, nsdsf2; \ | 
 | 159 |     local_irq_save(flags); \ | 
 | 160 |     save_flags(nsdsf); cli();\ | 
 | 161 |     if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ | 
 | 162 |                                 (flags)&(1<<9)?"en":"dis"); \ | 
 | 163 |     if (spin_is_locked(&(card)->res_lock) && \ | 
 | 164 |         (card)->cpu_res == smp_processor_id()) { \ | 
 | 165 |        printk("nicstar.c: line %d (cpu %d) res_lock already locked at line %d (cpu %d)\n", \ | 
 | 166 |               __LINE__, smp_processor_id(), (card)->has_res_lock, \ | 
 | 167 |               (card)->cpu_res); \ | 
 | 168 |        printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | 
 | 169 |     } \ | 
 | 170 |     spin_lock_irq(&(card)->res_lock); \ | 
 | 171 |     (card)->has_res_lock = __LINE__; \ | 
 | 172 |     (card)->cpu_res = smp_processor_id(); \ | 
 | 173 |     restore_flags(nsdsf); } while (0) | 
 | 174 | #define ns_grab_scq_lock(card,scq,flags) \ | 
 | 175 |  do { \ | 
 | 176 |     unsigned long nsdsf, nsdsf2; \ | 
 | 177 |     local_irq_save(flags); \ | 
 | 178 |     save_flags(nsdsf); cli();\ | 
 | 179 |     if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ | 
 | 180 |                                 (flags)&(1<<9)?"en":"dis"); \ | 
 | 181 |     if (spin_is_locked(&(scq)->lock) && \ | 
 | 182 |         (scq)->cpu_lock == smp_processor_id()) { \ | 
 | 183 |        printk("nicstar.c: line %d (cpu %d) this scq_lock already locked at line %d (cpu %d)\n", \ | 
 | 184 |               __LINE__, smp_processor_id(), (scq)->has_lock, \ | 
 | 185 |               (scq)->cpu_lock); \ | 
 | 186 |        printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | 
 | 187 |     } \ | 
 | 188 |     if (spin_is_locked(&(card)->res_lock) && \ | 
 | 189 |         (card)->cpu_res == smp_processor_id()) { \ | 
 | 190 |        printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying scq)\n", \ | 
 | 191 |               __LINE__, smp_processor_id(), (card)->has_res_lock, \ | 
 | 192 |               (card)->cpu_res); \ | 
 | 193 |        printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | 
 | 194 |     } \ | 
 | 195 |     spin_lock_irq(&(scq)->lock); \ | 
 | 196 |     (scq)->has_lock = __LINE__; \ | 
 | 197 |     (scq)->cpu_lock = smp_processor_id(); \ | 
 | 198 |     restore_flags(nsdsf); } while (0) | 
 | 199 | #else /* !NS_DEBUG_SPINLOCKS */ | 
 | 200 | #define ns_grab_int_lock(card,flags) \ | 
 | 201 |         spin_lock_irqsave(&(card)->int_lock,(flags)) | 
 | 202 | #define ns_grab_res_lock(card,flags) \ | 
 | 203 |         spin_lock_irqsave(&(card)->res_lock,(flags)) | 
 | 204 | #define ns_grab_scq_lock(card,scq,flags) \ | 
 | 205 |         spin_lock_irqsave(&(scq)->lock,flags) | 
 | 206 | #endif /* NS_DEBUG_SPINLOCKS */ | 
 | 207 |  | 
 | 208 |  | 
 | 209 | /* Function declarations ******************************************************/ | 
 | 210 |  | 
 | 211 | static u32 ns_read_sram(ns_dev *card, u32 sram_address); | 
 | 212 | static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count); | 
 | 213 | static int __devinit ns_init_card(int i, struct pci_dev *pcidev); | 
 | 214 | static void __devinit ns_init_card_error(ns_dev *card, int error); | 
 | 215 | static scq_info *get_scq(int size, u32 scd); | 
 | 216 | static void free_scq(scq_info *scq, struct atm_vcc *vcc); | 
 | 217 | static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, | 
 | 218 |                        u32 handle2, u32 addr2); | 
 | 219 | static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs); | 
 | 220 | static int ns_open(struct atm_vcc *vcc); | 
 | 221 | static void ns_close(struct atm_vcc *vcc); | 
 | 222 | static void fill_tst(ns_dev *card, int n, vc_map *vc); | 
 | 223 | static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb); | 
 | 224 | static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, | 
 | 225 |                      struct sk_buff *skb); | 
 | 226 | static void process_tsq(ns_dev *card); | 
 | 227 | static void drain_scq(ns_dev *card, scq_info *scq, int pos); | 
 | 228 | static void process_rsq(ns_dev *card); | 
 | 229 | static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe); | 
 | 230 | #ifdef NS_USE_DESTRUCTORS | 
 | 231 | static void ns_sb_destructor(struct sk_buff *sb); | 
 | 232 | static void ns_lb_destructor(struct sk_buff *lb); | 
 | 233 | static void ns_hb_destructor(struct sk_buff *hb); | 
 | 234 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 235 | static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb); | 
 | 236 | static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count); | 
 | 237 | static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb); | 
 | 238 | static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb); | 
 | 239 | static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb); | 
 | 240 | static int ns_proc_read(struct atm_dev *dev, loff_t *pos, char *page); | 
 | 241 | static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg); | 
 | 242 | static void which_list(ns_dev *card, struct sk_buff *skb); | 
 | 243 | static void ns_poll(unsigned long arg); | 
 | 244 | static int ns_parse_mac(char *mac, unsigned char *esi); | 
 | 245 | static short ns_h2i(char c); | 
 | 246 | static void ns_phy_put(struct atm_dev *dev, unsigned char value, | 
 | 247 |                        unsigned long addr); | 
 | 248 | static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr); | 
 | 249 |  | 
 | 250 |  | 
 | 251 |  | 
 | 252 | /* Global variables ***********************************************************/ | 
 | 253 |  | 
 | 254 | static struct ns_dev *cards[NS_MAX_CARDS]; | 
 | 255 | static unsigned num_cards; | 
 | 256 | static struct atmdev_ops atm_ops = | 
 | 257 | { | 
 | 258 |    .open	= ns_open, | 
 | 259 |    .close	= ns_close, | 
 | 260 |    .ioctl	= ns_ioctl, | 
 | 261 |    .send	= ns_send, | 
 | 262 |    .phy_put	= ns_phy_put, | 
 | 263 |    .phy_get	= ns_phy_get, | 
 | 264 |    .proc_read	= ns_proc_read, | 
 | 265 |    .owner	= THIS_MODULE, | 
 | 266 | }; | 
 | 267 | static struct timer_list ns_timer; | 
 | 268 | static char *mac[NS_MAX_CARDS]; | 
 | 269 | module_param_array(mac, charp, NULL, 0); | 
 | 270 | MODULE_LICENSE("GPL"); | 
 | 271 |  | 
 | 272 |  | 
 | 273 | /* Functions*******************************************************************/ | 
 | 274 |  | 
 | 275 | static int __devinit nicstar_init_one(struct pci_dev *pcidev, | 
 | 276 | 				      const struct pci_device_id *ent) | 
 | 277 | { | 
 | 278 |    static int index = -1; | 
 | 279 |    unsigned int error; | 
 | 280 |  | 
 | 281 |    index++; | 
 | 282 |    cards[index] = NULL; | 
 | 283 |  | 
 | 284 |    error = ns_init_card(index, pcidev); | 
 | 285 |    if (error) { | 
 | 286 |       cards[index--] = NULL;	/* don't increment index */ | 
 | 287 |       goto err_out; | 
 | 288 |    } | 
 | 289 |  | 
 | 290 |    return 0; | 
 | 291 | err_out: | 
 | 292 |    return -ENODEV; | 
 | 293 | } | 
 | 294 |  | 
 | 295 |  | 
 | 296 |  | 
 | 297 | static void __devexit nicstar_remove_one(struct pci_dev *pcidev) | 
 | 298 | { | 
 | 299 |    int i, j; | 
 | 300 |    ns_dev *card = pci_get_drvdata(pcidev); | 
 | 301 |    struct sk_buff *hb; | 
 | 302 |    struct sk_buff *iovb; | 
 | 303 |    struct sk_buff *lb; | 
 | 304 |    struct sk_buff *sb; | 
 | 305 |     | 
 | 306 |    i = card->index; | 
 | 307 |  | 
 | 308 |    if (cards[i] == NULL) | 
 | 309 |       return; | 
 | 310 |  | 
 | 311 |    if (card->atmdev->phy && card->atmdev->phy->stop) | 
 | 312 |       card->atmdev->phy->stop(card->atmdev); | 
 | 313 |  | 
 | 314 |    /* Stop everything */ | 
 | 315 |    writel(0x00000000, card->membase + CFG); | 
 | 316 |  | 
 | 317 |    /* De-register device */ | 
 | 318 |    atm_dev_deregister(card->atmdev); | 
 | 319 |  | 
 | 320 |    /* Disable PCI device */ | 
 | 321 |    pci_disable_device(pcidev); | 
 | 322 |     | 
 | 323 |    /* Free up resources */ | 
 | 324 |    j = 0; | 
 | 325 |    PRINTK("nicstar%d: freeing %d huge buffers.\n", i, card->hbpool.count); | 
 | 326 |    while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) | 
 | 327 |    { | 
 | 328 |       dev_kfree_skb_any(hb); | 
 | 329 |       j++; | 
 | 330 |    } | 
 | 331 |    PRINTK("nicstar%d: %d huge buffers freed.\n", i, j); | 
 | 332 |    j = 0; | 
 | 333 |    PRINTK("nicstar%d: freeing %d iovec buffers.\n", i, card->iovpool.count); | 
 | 334 |    while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) | 
 | 335 |    { | 
 | 336 |       dev_kfree_skb_any(iovb); | 
 | 337 |       j++; | 
 | 338 |    } | 
 | 339 |    PRINTK("nicstar%d: %d iovec buffers freed.\n", i, j); | 
 | 340 |    while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) | 
 | 341 |       dev_kfree_skb_any(lb); | 
 | 342 |    while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) | 
 | 343 |       dev_kfree_skb_any(sb); | 
 | 344 |    free_scq(card->scq0, NULL); | 
 | 345 |    for (j = 0; j < NS_FRSCD_NUM; j++) | 
 | 346 |    { | 
 | 347 |       if (card->scd2vc[j] != NULL) | 
 | 348 |          free_scq(card->scd2vc[j]->scq, card->scd2vc[j]->tx_vcc); | 
 | 349 |    } | 
 | 350 |    kfree(card->rsq.org); | 
 | 351 |    kfree(card->tsq.org); | 
 | 352 |    free_irq(card->pcidev->irq, card); | 
 | 353 |    iounmap(card->membase); | 
 | 354 |    kfree(card); | 
 | 355 | } | 
 | 356 |  | 
 | 357 |  | 
 | 358 |  | 
 | 359 | static struct pci_device_id nicstar_pci_tbl[] __devinitdata = | 
 | 360 | { | 
 | 361 | 	{PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_IDT_IDT77201, | 
 | 362 | 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 
 | 363 | 	{0,}			/* terminate list */ | 
 | 364 | }; | 
 | 365 | MODULE_DEVICE_TABLE(pci, nicstar_pci_tbl); | 
 | 366 |  | 
 | 367 |  | 
 | 368 |  | 
 | 369 | static struct pci_driver nicstar_driver = { | 
 | 370 | 	.name		= "nicstar", | 
 | 371 | 	.id_table	= nicstar_pci_tbl, | 
 | 372 | 	.probe		= nicstar_init_one, | 
 | 373 | 	.remove		= __devexit_p(nicstar_remove_one), | 
 | 374 | }; | 
 | 375 |  | 
 | 376 |  | 
 | 377 |  | 
 | 378 | static int __init nicstar_init(void) | 
 | 379 | { | 
 | 380 |    unsigned error = 0;	/* Initialized to remove compile warning */ | 
 | 381 |  | 
 | 382 |    XPRINTK("nicstar: nicstar_init() called.\n"); | 
 | 383 |  | 
 | 384 |    error = pci_register_driver(&nicstar_driver); | 
 | 385 |     | 
 | 386 |    TXPRINTK("nicstar: TX debug enabled.\n"); | 
 | 387 |    RXPRINTK("nicstar: RX debug enabled.\n"); | 
 | 388 |    PRINTK("nicstar: General debug enabled.\n"); | 
 | 389 | #ifdef PHY_LOOPBACK | 
 | 390 |    printk("nicstar: using PHY loopback.\n"); | 
 | 391 | #endif /* PHY_LOOPBACK */ | 
 | 392 |    XPRINTK("nicstar: nicstar_init() returned.\n"); | 
 | 393 |  | 
 | 394 |    if (!error) { | 
 | 395 |       init_timer(&ns_timer); | 
 | 396 |       ns_timer.expires = jiffies + NS_POLL_PERIOD; | 
 | 397 |       ns_timer.data = 0UL; | 
 | 398 |       ns_timer.function = ns_poll; | 
 | 399 |       add_timer(&ns_timer); | 
 | 400 |    } | 
 | 401 |     | 
 | 402 |    return error; | 
 | 403 | } | 
 | 404 |  | 
 | 405 |  | 
 | 406 |  | 
 | 407 | static void __exit nicstar_cleanup(void) | 
 | 408 | { | 
 | 409 |    XPRINTK("nicstar: nicstar_cleanup() called.\n"); | 
 | 410 |  | 
 | 411 |    del_timer(&ns_timer); | 
 | 412 |  | 
 | 413 |    pci_unregister_driver(&nicstar_driver); | 
 | 414 |  | 
 | 415 |    XPRINTK("nicstar: nicstar_cleanup() returned.\n"); | 
 | 416 | } | 
 | 417 |  | 
 | 418 |  | 
 | 419 |  | 
 | 420 | static u32 ns_read_sram(ns_dev *card, u32 sram_address) | 
 | 421 | { | 
 | 422 |    unsigned long flags; | 
 | 423 |    u32 data; | 
 | 424 |    sram_address <<= 2; | 
 | 425 |    sram_address &= 0x0007FFFC;	/* address must be dword aligned */ | 
 | 426 |    sram_address |= 0x50000000;	/* SRAM read command */ | 
 | 427 |    ns_grab_res_lock(card, flags); | 
 | 428 |    while (CMD_BUSY(card)); | 
 | 429 |    writel(sram_address, card->membase + CMD); | 
 | 430 |    while (CMD_BUSY(card)); | 
 | 431 |    data = readl(card->membase + DR0); | 
 | 432 |    spin_unlock_irqrestore(&card->res_lock, flags); | 
 | 433 |    return data; | 
 | 434 | } | 
 | 435 |  | 
 | 436 |  | 
 | 437 |     | 
 | 438 | static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count) | 
 | 439 | { | 
 | 440 |    unsigned long flags; | 
 | 441 |    int i, c; | 
 | 442 |    count--;	/* count range now is 0..3 instead of 1..4 */ | 
 | 443 |    c = count; | 
 | 444 |    c <<= 2;	/* to use increments of 4 */ | 
 | 445 |    ns_grab_res_lock(card, flags); | 
 | 446 |    while (CMD_BUSY(card)); | 
 | 447 |    for (i = 0; i <= c; i += 4) | 
 | 448 |       writel(*(value++), card->membase + i); | 
 | 449 |    /* Note: DR# registers are the first 4 dwords in nicstar's memspace, | 
 | 450 |             so card->membase + DR0 == card->membase */ | 
 | 451 |    sram_address <<= 2; | 
 | 452 |    sram_address &= 0x0007FFFC; | 
 | 453 |    sram_address |= (0x40000000 | count); | 
 | 454 |    writel(sram_address, card->membase + CMD); | 
 | 455 |    spin_unlock_irqrestore(&card->res_lock, flags); | 
 | 456 | } | 
 | 457 |  | 
 | 458 |  | 
 | 459 | static int __devinit ns_init_card(int i, struct pci_dev *pcidev) | 
 | 460 | { | 
 | 461 |    int j; | 
 | 462 |    struct ns_dev *card = NULL; | 
 | 463 |    unsigned char pci_latency; | 
 | 464 |    unsigned error; | 
 | 465 |    u32 data; | 
 | 466 |    u32 u32d[4]; | 
 | 467 |    u32 ns_cfg_rctsize; | 
 | 468 |    int bcount; | 
 | 469 |    unsigned long membase; | 
 | 470 |  | 
 | 471 |    error = 0; | 
 | 472 |  | 
 | 473 |    if (pci_enable_device(pcidev)) | 
 | 474 |    { | 
 | 475 |       printk("nicstar%d: can't enable PCI device\n", i); | 
 | 476 |       error = 2; | 
 | 477 |       ns_init_card_error(card, error); | 
 | 478 |       return error; | 
 | 479 |    } | 
 | 480 |  | 
 | 481 |    if ((card = kmalloc(sizeof(ns_dev), GFP_KERNEL)) == NULL) | 
 | 482 |    { | 
 | 483 |       printk("nicstar%d: can't allocate memory for device structure.\n", i); | 
 | 484 |       error = 2; | 
 | 485 |       ns_init_card_error(card, error); | 
 | 486 |       return error; | 
 | 487 |    } | 
 | 488 |    cards[i] = card; | 
 | 489 |    spin_lock_init(&card->int_lock); | 
 | 490 |    spin_lock_init(&card->res_lock); | 
 | 491 |        | 
 | 492 |    pci_set_drvdata(pcidev, card); | 
 | 493 |     | 
 | 494 |    card->index = i; | 
 | 495 |    card->atmdev = NULL; | 
 | 496 |    card->pcidev = pcidev; | 
 | 497 |    membase = pci_resource_start(pcidev, 1); | 
 | 498 |    card->membase = ioremap(membase, NS_IOREMAP_SIZE); | 
 | 499 |    if (card->membase == 0) | 
 | 500 |    { | 
 | 501 |       printk("nicstar%d: can't ioremap() membase.\n",i); | 
 | 502 |       error = 3; | 
 | 503 |       ns_init_card_error(card, error); | 
 | 504 |       return error; | 
 | 505 |    } | 
 | 506 |    PRINTK("nicstar%d: membase at 0x%x.\n", i, card->membase); | 
 | 507 |  | 
 | 508 |    pci_set_master(pcidev); | 
 | 509 |  | 
 | 510 |    if (pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency) != 0) | 
 | 511 |    { | 
 | 512 |       printk("nicstar%d: can't read PCI latency timer.\n", i); | 
 | 513 |       error = 6; | 
 | 514 |       ns_init_card_error(card, error); | 
 | 515 |       return error; | 
 | 516 |    } | 
 | 517 | #ifdef NS_PCI_LATENCY | 
 | 518 |    if (pci_latency < NS_PCI_LATENCY) | 
 | 519 |    { | 
 | 520 |       PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i, NS_PCI_LATENCY); | 
 | 521 |       for (j = 1; j < 4; j++) | 
 | 522 |       { | 
 | 523 |          if (pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0) | 
 | 524 | 	    break; | 
 | 525 |       } | 
 | 526 |       if (j == 4) | 
 | 527 |       { | 
 | 528 |          printk("nicstar%d: can't set PCI latency timer to %d.\n", i, NS_PCI_LATENCY); | 
 | 529 |          error = 7; | 
 | 530 |          ns_init_card_error(card, error); | 
 | 531 | 	 return error; | 
 | 532 |       } | 
 | 533 |    } | 
 | 534 | #endif /* NS_PCI_LATENCY */ | 
 | 535 |        | 
 | 536 |    /* Clear timer overflow */ | 
 | 537 |    data = readl(card->membase + STAT); | 
 | 538 |    if (data & NS_STAT_TMROF) | 
 | 539 |       writel(NS_STAT_TMROF, card->membase + STAT); | 
 | 540 |  | 
 | 541 |    /* Software reset */ | 
 | 542 |    writel(NS_CFG_SWRST, card->membase + CFG); | 
 | 543 |    NS_DELAY; | 
 | 544 |    writel(0x00000000, card->membase + CFG); | 
 | 545 |  | 
 | 546 |    /* PHY reset */ | 
 | 547 |    writel(0x00000008, card->membase + GP); | 
 | 548 |    NS_DELAY; | 
 | 549 |    writel(0x00000001, card->membase + GP); | 
 | 550 |    NS_DELAY; | 
 | 551 |    while (CMD_BUSY(card)); | 
 | 552 |    writel(NS_CMD_WRITE_UTILITY | 0x00000100, card->membase + CMD);	/* Sync UTOPIA with SAR clock */ | 
 | 553 |    NS_DELAY; | 
 | 554 |        | 
 | 555 |    /* Detect PHY type */ | 
 | 556 |    while (CMD_BUSY(card)); | 
 | 557 |    writel(NS_CMD_READ_UTILITY | 0x00000200, card->membase + CMD); | 
 | 558 |    while (CMD_BUSY(card)); | 
 | 559 |    data = readl(card->membase + DR0); | 
 | 560 |    switch(data) { | 
 | 561 |       case 0x00000009: | 
 | 562 |          printk("nicstar%d: PHY seems to be 25 Mbps.\n", i); | 
 | 563 |          card->max_pcr = ATM_25_PCR; | 
 | 564 |          while(CMD_BUSY(card)); | 
 | 565 |          writel(0x00000008, card->membase + DR0); | 
 | 566 |          writel(NS_CMD_WRITE_UTILITY | 0x00000200, card->membase + CMD); | 
 | 567 |          /* Clear an eventual pending interrupt */ | 
 | 568 |          writel(NS_STAT_SFBQF, card->membase + STAT); | 
 | 569 | #ifdef PHY_LOOPBACK | 
 | 570 |          while(CMD_BUSY(card)); | 
 | 571 |          writel(0x00000022, card->membase + DR0); | 
 | 572 |          writel(NS_CMD_WRITE_UTILITY | 0x00000202, card->membase + CMD); | 
 | 573 | #endif /* PHY_LOOPBACK */ | 
 | 574 | 	 break; | 
 | 575 |       case 0x00000030: | 
 | 576 |       case 0x00000031: | 
 | 577 |          printk("nicstar%d: PHY seems to be 155 Mbps.\n", i); | 
 | 578 |          card->max_pcr = ATM_OC3_PCR; | 
 | 579 | #ifdef PHY_LOOPBACK | 
 | 580 |          while(CMD_BUSY(card)); | 
 | 581 |          writel(0x00000002, card->membase + DR0); | 
 | 582 |          writel(NS_CMD_WRITE_UTILITY | 0x00000205, card->membase + CMD); | 
 | 583 | #endif /* PHY_LOOPBACK */ | 
 | 584 | 	 break; | 
 | 585 |       default: | 
 | 586 |          printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data); | 
 | 587 |          error = 8; | 
 | 588 |          ns_init_card_error(card, error); | 
 | 589 |          return error; | 
 | 590 |    } | 
 | 591 |    writel(0x00000000, card->membase + GP); | 
 | 592 |  | 
 | 593 |    /* Determine SRAM size */ | 
 | 594 |    data = 0x76543210; | 
 | 595 |    ns_write_sram(card, 0x1C003, &data, 1); | 
 | 596 |    data = 0x89ABCDEF; | 
 | 597 |    ns_write_sram(card, 0x14003, &data, 1); | 
 | 598 |    if (ns_read_sram(card, 0x14003) == 0x89ABCDEF && | 
 | 599 |        ns_read_sram(card, 0x1C003) == 0x76543210) | 
 | 600 |        card->sram_size = 128; | 
 | 601 |    else | 
 | 602 |       card->sram_size = 32; | 
 | 603 |    PRINTK("nicstar%d: %dK x 32bit SRAM size.\n", i, card->sram_size); | 
 | 604 |  | 
 | 605 |    card->rct_size = NS_MAX_RCTSIZE; | 
 | 606 |  | 
 | 607 | #if (NS_MAX_RCTSIZE == 4096) | 
 | 608 |    if (card->sram_size == 128) | 
 | 609 |       printk("nicstar%d: limiting maximum VCI. See NS_MAX_RCTSIZE in nicstar.h\n", i); | 
 | 610 | #elif (NS_MAX_RCTSIZE == 16384) | 
 | 611 |    if (card->sram_size == 32) | 
 | 612 |    { | 
 | 613 |       printk("nicstar%d: wasting memory. See NS_MAX_RCTSIZE in nicstar.h\n", i); | 
 | 614 |       card->rct_size = 4096; | 
 | 615 |    } | 
 | 616 | #else | 
 | 617 | #error NS_MAX_RCTSIZE must be either 4096 or 16384 in nicstar.c | 
 | 618 | #endif | 
 | 619 |  | 
 | 620 |    card->vpibits = NS_VPIBITS; | 
 | 621 |    if (card->rct_size == 4096) | 
 | 622 |       card->vcibits = 12 - NS_VPIBITS; | 
 | 623 |    else /* card->rct_size == 16384 */ | 
 | 624 |       card->vcibits = 14 - NS_VPIBITS; | 
 | 625 |  | 
 | 626 |    /* Initialize the nicstar eeprom/eprom stuff, for the MAC addr */ | 
 | 627 |    if (mac[i] == NULL) | 
 | 628 |       nicstar_init_eprom(card->membase); | 
 | 629 |  | 
 | 630 |    if (request_irq(pcidev->irq, &ns_irq_handler, SA_INTERRUPT | SA_SHIRQ, "nicstar", card) != 0) | 
 | 631 |    { | 
 | 632 |       printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); | 
 | 633 |       error = 9; | 
 | 634 |       ns_init_card_error(card, error); | 
 | 635 |       return error; | 
 | 636 |    } | 
 | 637 |  | 
 | 638 |    /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ | 
 | 639 |    writel(0x00000000, card->membase + VPM); | 
 | 640 |        | 
 | 641 |    /* Initialize TSQ */ | 
 | 642 |    card->tsq.org = kmalloc(NS_TSQSIZE + NS_TSQ_ALIGNMENT, GFP_KERNEL); | 
 | 643 |    if (card->tsq.org == NULL) | 
 | 644 |    { | 
 | 645 |       printk("nicstar%d: can't allocate TSQ.\n", i); | 
 | 646 |       error = 10; | 
 | 647 |       ns_init_card_error(card, error); | 
 | 648 |       return error; | 
 | 649 |    } | 
 | 650 |    card->tsq.base = (ns_tsi *) ALIGN_ADDRESS(card->tsq.org, NS_TSQ_ALIGNMENT); | 
 | 651 |    card->tsq.next = card->tsq.base; | 
 | 652 |    card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1); | 
 | 653 |    for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++) | 
 | 654 |       ns_tsi_init(card->tsq.base + j); | 
 | 655 |    writel(0x00000000, card->membase + TSQH); | 
 | 656 |    writel((u32) virt_to_bus(card->tsq.base), card->membase + TSQB); | 
 | 657 |    PRINTK("nicstar%d: TSQ base at 0x%x  0x%x  0x%x.\n", i, (u32) card->tsq.base, | 
 | 658 |           (u32) virt_to_bus(card->tsq.base), readl(card->membase + TSQB)); | 
 | 659 |        | 
 | 660 |    /* Initialize RSQ */ | 
 | 661 |    card->rsq.org = kmalloc(NS_RSQSIZE + NS_RSQ_ALIGNMENT, GFP_KERNEL); | 
 | 662 |    if (card->rsq.org == NULL) | 
 | 663 |    { | 
 | 664 |       printk("nicstar%d: can't allocate RSQ.\n", i); | 
 | 665 |       error = 11; | 
 | 666 |       ns_init_card_error(card, error); | 
 | 667 |       return error; | 
 | 668 |    } | 
 | 669 |    card->rsq.base = (ns_rsqe *) ALIGN_ADDRESS(card->rsq.org, NS_RSQ_ALIGNMENT); | 
 | 670 |    card->rsq.next = card->rsq.base; | 
 | 671 |    card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1); | 
 | 672 |    for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++) | 
 | 673 |       ns_rsqe_init(card->rsq.base + j); | 
 | 674 |    writel(0x00000000, card->membase + RSQH); | 
 | 675 |    writel((u32) virt_to_bus(card->rsq.base), card->membase + RSQB); | 
 | 676 |    PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base); | 
 | 677 |        | 
 | 678 |    /* Initialize SCQ0, the only VBR SCQ used */ | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 679 |    card->scq1 = NULL; | 
 | 680 |    card->scq2 = NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 681 |    card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0); | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 682 |    if (card->scq0 == NULL) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 683 |    { | 
 | 684 |       printk("nicstar%d: can't get SCQ0.\n", i); | 
 | 685 |       error = 12; | 
 | 686 |       ns_init_card_error(card, error); | 
 | 687 |       return error; | 
 | 688 |    } | 
 | 689 |    u32d[0] = (u32) virt_to_bus(card->scq0->base); | 
 | 690 |    u32d[1] = (u32) 0x00000000; | 
 | 691 |    u32d[2] = (u32) 0xffffffff; | 
 | 692 |    u32d[3] = (u32) 0x00000000; | 
 | 693 |    ns_write_sram(card, NS_VRSCD0, u32d, 4); | 
 | 694 |    ns_write_sram(card, NS_VRSCD1, u32d, 4);	/* These last two won't be used */ | 
 | 695 |    ns_write_sram(card, NS_VRSCD2, u32d, 4);	/* but are initialized, just in case... */ | 
 | 696 |    card->scq0->scd = NS_VRSCD0; | 
 | 697 |    PRINTK("nicstar%d: VBR-SCQ0 base at 0x%x.\n", i, (u32) card->scq0->base); | 
 | 698 |  | 
 | 699 |    /* Initialize TSTs */ | 
 | 700 |    card->tst_addr = NS_TST0; | 
 | 701 |    card->tst_free_entries = NS_TST_NUM_ENTRIES; | 
 | 702 |    data = NS_TST_OPCODE_VARIABLE; | 
 | 703 |    for (j = 0; j < NS_TST_NUM_ENTRIES; j++) | 
 | 704 |       ns_write_sram(card, NS_TST0 + j, &data, 1); | 
 | 705 |    data = ns_tste_make(NS_TST_OPCODE_END, NS_TST0); | 
 | 706 |    ns_write_sram(card, NS_TST0 + NS_TST_NUM_ENTRIES, &data, 1); | 
 | 707 |    for (j = 0; j < NS_TST_NUM_ENTRIES; j++) | 
 | 708 |       ns_write_sram(card, NS_TST1 + j, &data, 1); | 
 | 709 |    data = ns_tste_make(NS_TST_OPCODE_END, NS_TST1); | 
 | 710 |    ns_write_sram(card, NS_TST1 + NS_TST_NUM_ENTRIES, &data, 1); | 
 | 711 |    for (j = 0; j < NS_TST_NUM_ENTRIES; j++) | 
 | 712 |       card->tste2vc[j] = NULL; | 
 | 713 |    writel(NS_TST0 << 2, card->membase + TSTB); | 
 | 714 |  | 
 | 715 |  | 
 | 716 |    /* Initialize RCT. AAL type is set on opening the VC. */ | 
 | 717 | #ifdef RCQ_SUPPORT | 
 | 718 |    u32d[0] = NS_RCTE_RAWCELLINTEN; | 
 | 719 | #else | 
 | 720 |    u32d[0] = 0x00000000; | 
 | 721 | #endif /* RCQ_SUPPORT */ | 
 | 722 |    u32d[1] = 0x00000000; | 
 | 723 |    u32d[2] = 0x00000000; | 
 | 724 |    u32d[3] = 0xFFFFFFFF; | 
 | 725 |    for (j = 0; j < card->rct_size; j++) | 
 | 726 |       ns_write_sram(card, j * 4, u32d, 4);       | 
 | 727 |        | 
 | 728 |    memset(card->vcmap, 0, NS_MAX_RCTSIZE * sizeof(vc_map)); | 
 | 729 |        | 
 | 730 |    for (j = 0; j < NS_FRSCD_NUM; j++) | 
 | 731 |       card->scd2vc[j] = NULL; | 
 | 732 |  | 
 | 733 |    /* Initialize buffer levels */ | 
 | 734 |    card->sbnr.min = MIN_SB; | 
 | 735 |    card->sbnr.init = NUM_SB; | 
 | 736 |    card->sbnr.max = MAX_SB; | 
 | 737 |    card->lbnr.min = MIN_LB; | 
 | 738 |    card->lbnr.init = NUM_LB; | 
 | 739 |    card->lbnr.max = MAX_LB; | 
 | 740 |    card->iovnr.min = MIN_IOVB; | 
 | 741 |    card->iovnr.init = NUM_IOVB; | 
 | 742 |    card->iovnr.max = MAX_IOVB; | 
 | 743 |    card->hbnr.min = MIN_HB; | 
 | 744 |    card->hbnr.init = NUM_HB; | 
 | 745 |    card->hbnr.max = MAX_HB; | 
 | 746 |     | 
 | 747 |    card->sm_handle = 0x00000000; | 
 | 748 |    card->sm_addr = 0x00000000; | 
 | 749 |    card->lg_handle = 0x00000000; | 
 | 750 |    card->lg_addr = 0x00000000; | 
 | 751 |     | 
 | 752 |    card->efbie = 1;	/* To prevent push_rxbufs from enabling the interrupt */ | 
 | 753 |  | 
 | 754 |    /* Pre-allocate some huge buffers */ | 
 | 755 |    skb_queue_head_init(&card->hbpool.queue); | 
 | 756 |    card->hbpool.count = 0; | 
 | 757 |    for (j = 0; j < NUM_HB; j++) | 
 | 758 |    { | 
 | 759 |       struct sk_buff *hb; | 
 | 760 |       hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); | 
 | 761 |       if (hb == NULL) | 
 | 762 |       { | 
 | 763 |          printk("nicstar%d: can't allocate %dth of %d huge buffers.\n", | 
 | 764 |                 i, j, NUM_HB); | 
 | 765 |          error = 13; | 
 | 766 |          ns_init_card_error(card, error); | 
 | 767 | 	 return error; | 
 | 768 |       } | 
 | 769 |       skb_queue_tail(&card->hbpool.queue, hb); | 
 | 770 |       card->hbpool.count++; | 
 | 771 |    } | 
 | 772 |  | 
 | 773 |  | 
 | 774 |    /* Allocate large buffers */ | 
 | 775 |    skb_queue_head_init(&card->lbpool.queue); | 
 | 776 |    card->lbpool.count = 0;			/* Not used */ | 
 | 777 |    for (j = 0; j < NUM_LB; j++) | 
 | 778 |    { | 
 | 779 |       struct sk_buff *lb; | 
 | 780 |       lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); | 
 | 781 |       if (lb == NULL) | 
 | 782 |       { | 
 | 783 |          printk("nicstar%d: can't allocate %dth of %d large buffers.\n", | 
 | 784 |                 i, j, NUM_LB); | 
 | 785 |          error = 14; | 
 | 786 |          ns_init_card_error(card, error); | 
 | 787 | 	 return error; | 
 | 788 |       } | 
 | 789 |       skb_queue_tail(&card->lbpool.queue, lb); | 
 | 790 |       skb_reserve(lb, NS_SMBUFSIZE); | 
 | 791 |       push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | 
 | 792 |       /* Due to the implementation of push_rxbufs() this is 1, not 0 */ | 
 | 793 |       if (j == 1) | 
 | 794 |       { | 
 | 795 |          card->rcbuf = lb; | 
 | 796 |          card->rawch = (u32) virt_to_bus(lb->data); | 
 | 797 |       } | 
 | 798 |    } | 
 | 799 |    /* Test for strange behaviour which leads to crashes */ | 
 | 800 |    if ((bcount = ns_stat_lfbqc_get(readl(card->membase + STAT))) < card->lbnr.min) | 
 | 801 |    { | 
 | 802 |       printk("nicstar%d: Strange... Just allocated %d large buffers and lfbqc = %d.\n", | 
 | 803 |              i, j, bcount); | 
 | 804 |       error = 14; | 
 | 805 |       ns_init_card_error(card, error); | 
 | 806 |       return error; | 
 | 807 |    } | 
 | 808 |        | 
 | 809 |  | 
 | 810 |    /* Allocate small buffers */ | 
 | 811 |    skb_queue_head_init(&card->sbpool.queue); | 
 | 812 |    card->sbpool.count = 0;			/* Not used */ | 
 | 813 |    for (j = 0; j < NUM_SB; j++) | 
 | 814 |    { | 
 | 815 |       struct sk_buff *sb; | 
 | 816 |       sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); | 
 | 817 |       if (sb == NULL) | 
 | 818 |       { | 
 | 819 |          printk("nicstar%d: can't allocate %dth of %d small buffers.\n", | 
 | 820 |                 i, j, NUM_SB); | 
 | 821 |          error = 15; | 
 | 822 |          ns_init_card_error(card, error); | 
 | 823 | 	 return error; | 
 | 824 |       } | 
 | 825 |       skb_queue_tail(&card->sbpool.queue, sb); | 
 | 826 |       skb_reserve(sb, NS_AAL0_HEADER); | 
 | 827 |       push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | 
 | 828 |    } | 
 | 829 |    /* Test for strange behaviour which leads to crashes */ | 
 | 830 |    if ((bcount = ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min) | 
 | 831 |    { | 
 | 832 |       printk("nicstar%d: Strange... Just allocated %d small buffers and sfbqc = %d.\n", | 
 | 833 |              i, j, bcount); | 
 | 834 |       error = 15; | 
 | 835 |       ns_init_card_error(card, error); | 
 | 836 |       return error; | 
 | 837 |    } | 
 | 838 |        | 
 | 839 |  | 
 | 840 |    /* Allocate iovec buffers */ | 
 | 841 |    skb_queue_head_init(&card->iovpool.queue); | 
 | 842 |    card->iovpool.count = 0; | 
 | 843 |    for (j = 0; j < NUM_IOVB; j++) | 
 | 844 |    { | 
 | 845 |       struct sk_buff *iovb; | 
 | 846 |       iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); | 
 | 847 |       if (iovb == NULL) | 
 | 848 |       { | 
 | 849 |          printk("nicstar%d: can't allocate %dth of %d iovec buffers.\n", | 
 | 850 |                 i, j, NUM_IOVB); | 
 | 851 |          error = 16; | 
 | 852 |          ns_init_card_error(card, error); | 
 | 853 | 	 return error; | 
 | 854 |       } | 
 | 855 |       skb_queue_tail(&card->iovpool.queue, iovb); | 
 | 856 |       card->iovpool.count++; | 
 | 857 |    } | 
 | 858 |  | 
 | 859 |    card->intcnt = 0; | 
 | 860 |  | 
 | 861 |    /* Configure NICStAR */ | 
 | 862 |    if (card->rct_size == 4096) | 
 | 863 |       ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES; | 
 | 864 |    else /* (card->rct_size == 16384) */ | 
 | 865 |       ns_cfg_rctsize = NS_CFG_RCTSIZE_16384_ENTRIES; | 
 | 866 |  | 
 | 867 |    card->efbie = 1; | 
 | 868 |  | 
 | 869 |    /* Register device */ | 
 | 870 |    card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL); | 
 | 871 |    if (card->atmdev == NULL) | 
 | 872 |    { | 
 | 873 |       printk("nicstar%d: can't register device.\n", i); | 
 | 874 |       error = 17; | 
 | 875 |       ns_init_card_error(card, error); | 
 | 876 |       return error; | 
 | 877 |    } | 
 | 878 |        | 
 | 879 |    if (ns_parse_mac(mac[i], card->atmdev->esi)) { | 
 | 880 |       nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET, | 
 | 881 |                          card->atmdev->esi, 6); | 
 | 882 |       if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) == 0) { | 
 | 883 |          nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT, | 
 | 884 |                          card->atmdev->esi, 6); | 
 | 885 |       } | 
 | 886 |    } | 
 | 887 |  | 
 | 888 |    printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i, | 
 | 889 |           card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2], | 
 | 890 |           card->atmdev->esi[3], card->atmdev->esi[4], card->atmdev->esi[5]); | 
 | 891 |  | 
 | 892 |    card->atmdev->dev_data = card; | 
 | 893 |    card->atmdev->ci_range.vpi_bits = card->vpibits; | 
 | 894 |    card->atmdev->ci_range.vci_bits = card->vcibits; | 
 | 895 |    card->atmdev->link_rate = card->max_pcr; | 
 | 896 |    card->atmdev->phy = NULL; | 
 | 897 |  | 
 | 898 | #ifdef CONFIG_ATM_NICSTAR_USE_SUNI | 
 | 899 |    if (card->max_pcr == ATM_OC3_PCR) | 
 | 900 |       suni_init(card->atmdev); | 
 | 901 | #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ | 
 | 902 |  | 
 | 903 | #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105 | 
 | 904 |    if (card->max_pcr == ATM_25_PCR) | 
 | 905 |       idt77105_init(card->atmdev); | 
 | 906 | #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ | 
 | 907 |  | 
 | 908 |    if (card->atmdev->phy && card->atmdev->phy->start) | 
 | 909 |       card->atmdev->phy->start(card->atmdev); | 
 | 910 |  | 
 | 911 |    writel(NS_CFG_RXPATH | | 
 | 912 |           NS_CFG_SMBUFSIZE | | 
 | 913 |           NS_CFG_LGBUFSIZE | | 
 | 914 |           NS_CFG_EFBIE | | 
 | 915 |           NS_CFG_RSQSIZE | | 
 | 916 |           NS_CFG_VPIBITS | | 
 | 917 |           ns_cfg_rctsize | | 
 | 918 |           NS_CFG_RXINT_NODELAY | | 
 | 919 |           NS_CFG_RAWIE |		/* Only enabled if RCQ_SUPPORT */ | 
 | 920 |           NS_CFG_RSQAFIE | | 
 | 921 |           NS_CFG_TXEN | | 
 | 922 |           NS_CFG_TXIE | | 
 | 923 |           NS_CFG_TSQFIE_OPT |		/* Only enabled if ENABLE_TSQFIE */  | 
 | 924 |           NS_CFG_PHYIE, | 
 | 925 |           card->membase + CFG); | 
 | 926 |  | 
 | 927 |    num_cards++; | 
 | 928 |  | 
 | 929 |    return error; | 
 | 930 | } | 
 | 931 |  | 
 | 932 |  | 
 | 933 |  | 
 | 934 | static void __devinit ns_init_card_error(ns_dev *card, int error) | 
 | 935 | { | 
 | 936 |    if (error >= 17) | 
 | 937 |    { | 
 | 938 |       writel(0x00000000, card->membase + CFG); | 
 | 939 |    } | 
 | 940 |    if (error >= 16) | 
 | 941 |    { | 
 | 942 |       struct sk_buff *iovb; | 
 | 943 |       while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) | 
 | 944 |          dev_kfree_skb_any(iovb); | 
 | 945 |    } | 
 | 946 |    if (error >= 15) | 
 | 947 |    { | 
 | 948 |       struct sk_buff *sb; | 
 | 949 |       while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) | 
 | 950 |          dev_kfree_skb_any(sb); | 
 | 951 |       free_scq(card->scq0, NULL); | 
 | 952 |    } | 
 | 953 |    if (error >= 14) | 
 | 954 |    { | 
 | 955 |       struct sk_buff *lb; | 
 | 956 |       while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) | 
 | 957 |          dev_kfree_skb_any(lb); | 
 | 958 |    } | 
 | 959 |    if (error >= 13) | 
 | 960 |    { | 
 | 961 |       struct sk_buff *hb; | 
 | 962 |       while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) | 
 | 963 |          dev_kfree_skb_any(hb); | 
 | 964 |    } | 
 | 965 |    if (error >= 12) | 
 | 966 |    { | 
 | 967 |       kfree(card->rsq.org); | 
 | 968 |    } | 
 | 969 |    if (error >= 11) | 
 | 970 |    { | 
 | 971 |       kfree(card->tsq.org); | 
 | 972 |    } | 
 | 973 |    if (error >= 10) | 
 | 974 |    { | 
 | 975 |       free_irq(card->pcidev->irq, card); | 
 | 976 |    } | 
 | 977 |    if (error >= 4) | 
 | 978 |    { | 
 | 979 |       iounmap(card->membase); | 
 | 980 |    } | 
 | 981 |    if (error >= 3) | 
 | 982 |    { | 
 | 983 |       pci_disable_device(card->pcidev); | 
 | 984 |       kfree(card); | 
 | 985 |    } | 
 | 986 | } | 
 | 987 |  | 
 | 988 |  | 
 | 989 |  | 
 | 990 | static scq_info *get_scq(int size, u32 scd) | 
 | 991 | { | 
 | 992 |    scq_info *scq; | 
 | 993 |    int i; | 
 | 994 |  | 
 | 995 |    if (size != VBR_SCQSIZE && size != CBR_SCQSIZE) | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 996 |       return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 997 |  | 
 | 998 |    scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL); | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 999 |    if (scq == NULL) | 
 | 1000 |       return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1001 |    scq->org = kmalloc(2 * size, GFP_KERNEL); | 
 | 1002 |    if (scq->org == NULL) | 
 | 1003 |    { | 
 | 1004 |       kfree(scq); | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 1005 |       return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1006 |    } | 
 | 1007 |    scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) * | 
 | 1008 |                                           (size / NS_SCQE_SIZE), GFP_KERNEL); | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 1009 |    if (scq->skb == NULL) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1010 |    { | 
 | 1011 |       kfree(scq->org); | 
 | 1012 |       kfree(scq); | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 1013 |       return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1014 |    } | 
 | 1015 |    scq->num_entries = size / NS_SCQE_SIZE; | 
 | 1016 |    scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size); | 
 | 1017 |    scq->next = scq->base; | 
 | 1018 |    scq->last = scq->base + (scq->num_entries - 1); | 
 | 1019 |    scq->tail = scq->last; | 
 | 1020 |    scq->scd = scd; | 
 | 1021 |    scq->num_entries = size / NS_SCQE_SIZE; | 
 | 1022 |    scq->tbd_count = 0; | 
 | 1023 |    init_waitqueue_head(&scq->scqfull_waitq); | 
 | 1024 |    scq->full = 0; | 
 | 1025 |    spin_lock_init(&scq->lock); | 
 | 1026 |  | 
 | 1027 |    for (i = 0; i < scq->num_entries; i++) | 
 | 1028 |       scq->skb[i] = NULL; | 
 | 1029 |  | 
 | 1030 |    return scq; | 
 | 1031 | } | 
 | 1032 |  | 
 | 1033 |  | 
 | 1034 |  | 
 | 1035 | /* For variable rate SCQ vcc must be NULL */ | 
 | 1036 | static void free_scq(scq_info *scq, struct atm_vcc *vcc) | 
 | 1037 | { | 
 | 1038 |    int i; | 
 | 1039 |  | 
 | 1040 |    if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) | 
 | 1041 |       for (i = 0; i < scq->num_entries; i++) | 
 | 1042 |       { | 
 | 1043 |          if (scq->skb[i] != NULL) | 
 | 1044 | 	 { | 
 | 1045 |             vcc = ATM_SKB(scq->skb[i])->vcc; | 
 | 1046 |             if (vcc->pop != NULL) | 
 | 1047 | 	       vcc->pop(vcc, scq->skb[i]); | 
 | 1048 | 	    else | 
 | 1049 |                dev_kfree_skb_any(scq->skb[i]); | 
 | 1050 |          } | 
 | 1051 |       } | 
 | 1052 |    else /* vcc must be != NULL */ | 
 | 1053 |    { | 
 | 1054 |       if (vcc == NULL) | 
 | 1055 |       { | 
 | 1056 |          printk("nicstar: free_scq() called with vcc == NULL for fixed rate scq."); | 
 | 1057 |          for (i = 0; i < scq->num_entries; i++) | 
 | 1058 |             dev_kfree_skb_any(scq->skb[i]); | 
 | 1059 |       } | 
 | 1060 |       else | 
 | 1061 |          for (i = 0; i < scq->num_entries; i++) | 
 | 1062 |          { | 
 | 1063 |             if (scq->skb[i] != NULL) | 
 | 1064 |             { | 
 | 1065 |                if (vcc->pop != NULL) | 
 | 1066 |                   vcc->pop(vcc, scq->skb[i]); | 
 | 1067 |                else | 
 | 1068 |                   dev_kfree_skb_any(scq->skb[i]); | 
 | 1069 |             } | 
 | 1070 |          } | 
 | 1071 |    } | 
 | 1072 |    kfree(scq->skb); | 
 | 1073 |    kfree(scq->org); | 
 | 1074 |    kfree(scq); | 
 | 1075 | } | 
 | 1076 |  | 
 | 1077 |  | 
 | 1078 |  | 
 | 1079 | /* The handles passed must be pointers to the sk_buff containing the small | 
 | 1080 |    or large buffer(s) cast to u32. */ | 
 | 1081 | static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, | 
 | 1082 |                        u32 handle2, u32 addr2) | 
 | 1083 | { | 
 | 1084 |    u32 stat; | 
 | 1085 |    unsigned long flags; | 
 | 1086 |     | 
 | 1087 |  | 
 | 1088 | #ifdef GENERAL_DEBUG | 
 | 1089 |    if (!addr1) | 
 | 1090 |       printk("nicstar%d: push_rxbufs called with addr1 = 0.\n", card->index); | 
 | 1091 | #endif /* GENERAL_DEBUG */ | 
 | 1092 |  | 
 | 1093 |    stat = readl(card->membase + STAT); | 
 | 1094 |    card->sbfqc = ns_stat_sfbqc_get(stat); | 
 | 1095 |    card->lbfqc = ns_stat_lfbqc_get(stat); | 
 | 1096 |    if (type == BUF_SM) | 
 | 1097 |    { | 
 | 1098 |       if (!addr2) | 
 | 1099 |       { | 
 | 1100 |          if (card->sm_addr) | 
 | 1101 | 	 { | 
 | 1102 | 	    addr2 = card->sm_addr; | 
 | 1103 | 	    handle2 = card->sm_handle; | 
 | 1104 | 	    card->sm_addr = 0x00000000; | 
 | 1105 | 	    card->sm_handle = 0x00000000; | 
 | 1106 | 	 } | 
 | 1107 | 	 else /* (!sm_addr) */ | 
 | 1108 | 	 { | 
 | 1109 | 	    card->sm_addr = addr1; | 
 | 1110 | 	    card->sm_handle = handle1; | 
 | 1111 | 	 } | 
 | 1112 |       }       | 
 | 1113 |    } | 
 | 1114 |    else /* type == BUF_LG */ | 
 | 1115 |    { | 
 | 1116 |       if (!addr2) | 
 | 1117 |       { | 
 | 1118 |          if (card->lg_addr) | 
 | 1119 | 	 { | 
 | 1120 | 	    addr2 = card->lg_addr; | 
 | 1121 | 	    handle2 = card->lg_handle; | 
 | 1122 | 	    card->lg_addr = 0x00000000; | 
 | 1123 | 	    card->lg_handle = 0x00000000; | 
 | 1124 | 	 } | 
 | 1125 | 	 else /* (!lg_addr) */ | 
 | 1126 | 	 { | 
 | 1127 | 	    card->lg_addr = addr1; | 
 | 1128 | 	    card->lg_handle = handle1; | 
 | 1129 | 	 } | 
 | 1130 |       }       | 
 | 1131 |    } | 
 | 1132 |  | 
 | 1133 |    if (addr2) | 
 | 1134 |    { | 
 | 1135 |       if (type == BUF_SM) | 
 | 1136 |       { | 
 | 1137 |          if (card->sbfqc >= card->sbnr.max) | 
 | 1138 |          { | 
 | 1139 |             skb_unlink((struct sk_buff *) handle1); | 
 | 1140 |             dev_kfree_skb_any((struct sk_buff *) handle1); | 
 | 1141 |             skb_unlink((struct sk_buff *) handle2); | 
 | 1142 |             dev_kfree_skb_any((struct sk_buff *) handle2); | 
 | 1143 |             return; | 
 | 1144 |          } | 
 | 1145 | 	 else | 
 | 1146 |             card->sbfqc += 2; | 
 | 1147 |       } | 
 | 1148 |       else /* (type == BUF_LG) */ | 
 | 1149 |       { | 
 | 1150 |          if (card->lbfqc >= card->lbnr.max) | 
 | 1151 |          { | 
 | 1152 |             skb_unlink((struct sk_buff *) handle1); | 
 | 1153 |             dev_kfree_skb_any((struct sk_buff *) handle1); | 
 | 1154 |             skb_unlink((struct sk_buff *) handle2); | 
 | 1155 |             dev_kfree_skb_any((struct sk_buff *) handle2); | 
 | 1156 |             return; | 
 | 1157 |          } | 
 | 1158 |          else | 
 | 1159 |             card->lbfqc += 2; | 
 | 1160 |       } | 
 | 1161 |  | 
 | 1162 |       ns_grab_res_lock(card, flags); | 
 | 1163 |  | 
 | 1164 |       while (CMD_BUSY(card)); | 
 | 1165 |       writel(addr2, card->membase + DR3); | 
 | 1166 |       writel(handle2, card->membase + DR2); | 
 | 1167 |       writel(addr1, card->membase + DR1); | 
 | 1168 |       writel(handle1, card->membase + DR0); | 
 | 1169 |       writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD); | 
 | 1170 |   | 
 | 1171 |       spin_unlock_irqrestore(&card->res_lock, flags); | 
 | 1172 |  | 
 | 1173 |       XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index, | 
 | 1174 |               (type == BUF_SM ? "small" : "large"), addr1, addr2); | 
 | 1175 |    } | 
 | 1176 |  | 
 | 1177 |    if (!card->efbie && card->sbfqc >= card->sbnr.min && | 
 | 1178 |        card->lbfqc >= card->lbnr.min) | 
 | 1179 |    { | 
 | 1180 |       card->efbie = 1; | 
 | 1181 |       writel((readl(card->membase + CFG) | NS_CFG_EFBIE), card->membase + CFG); | 
 | 1182 |    } | 
 | 1183 |  | 
 | 1184 |    return; | 
 | 1185 | } | 
 | 1186 |  | 
 | 1187 |  | 
 | 1188 |  | 
 | 1189 | static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | 
 | 1190 | { | 
 | 1191 |    u32 stat_r; | 
 | 1192 |    ns_dev *card; | 
 | 1193 |    struct atm_dev *dev; | 
 | 1194 |    unsigned long flags; | 
 | 1195 |  | 
 | 1196 |    card = (ns_dev *) dev_id; | 
 | 1197 |    dev = card->atmdev; | 
 | 1198 |    card->intcnt++; | 
 | 1199 |  | 
 | 1200 |    PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index); | 
 | 1201 |  | 
 | 1202 |    ns_grab_int_lock(card, flags); | 
 | 1203 |     | 
 | 1204 |    stat_r = readl(card->membase + STAT); | 
 | 1205 |  | 
 | 1206 |    /* Transmit Status Indicator has been written to T. S. Queue */ | 
 | 1207 |    if (stat_r & NS_STAT_TSIF) | 
 | 1208 |    { | 
 | 1209 |       TXPRINTK("nicstar%d: TSI interrupt\n", card->index); | 
 | 1210 |       process_tsq(card); | 
 | 1211 |       writel(NS_STAT_TSIF, card->membase + STAT); | 
 | 1212 |    } | 
 | 1213 |     | 
 | 1214 |    /* Incomplete CS-PDU has been transmitted */ | 
 | 1215 |    if (stat_r & NS_STAT_TXICP) | 
 | 1216 |    { | 
 | 1217 |       writel(NS_STAT_TXICP, card->membase + STAT); | 
 | 1218 |       TXPRINTK("nicstar%d: Incomplete CS-PDU transmitted.\n", | 
 | 1219 |                card->index); | 
 | 1220 |    } | 
 | 1221 |     | 
 | 1222 |    /* Transmit Status Queue 7/8 full */ | 
 | 1223 |    if (stat_r & NS_STAT_TSQF) | 
 | 1224 |    { | 
 | 1225 |       writel(NS_STAT_TSQF, card->membase + STAT); | 
 | 1226 |       PRINTK("nicstar%d: TSQ full.\n", card->index); | 
 | 1227 |       process_tsq(card); | 
 | 1228 |    } | 
 | 1229 |     | 
 | 1230 |    /* Timer overflow */ | 
 | 1231 |    if (stat_r & NS_STAT_TMROF) | 
 | 1232 |    { | 
 | 1233 |       writel(NS_STAT_TMROF, card->membase + STAT); | 
 | 1234 |       PRINTK("nicstar%d: Timer overflow.\n", card->index); | 
 | 1235 |    } | 
 | 1236 |     | 
 | 1237 |    /* PHY device interrupt signal active */ | 
 | 1238 |    if (stat_r & NS_STAT_PHYI) | 
 | 1239 |    { | 
 | 1240 |       writel(NS_STAT_PHYI, card->membase + STAT); | 
 | 1241 |       PRINTK("nicstar%d: PHY interrupt.\n", card->index); | 
 | 1242 |       if (dev->phy && dev->phy->interrupt) { | 
 | 1243 |          dev->phy->interrupt(dev); | 
 | 1244 |       } | 
 | 1245 |    } | 
 | 1246 |  | 
 | 1247 |    /* Small Buffer Queue is full */ | 
 | 1248 |    if (stat_r & NS_STAT_SFBQF) | 
 | 1249 |    { | 
 | 1250 |       writel(NS_STAT_SFBQF, card->membase + STAT); | 
 | 1251 |       printk("nicstar%d: Small free buffer queue is full.\n", card->index); | 
 | 1252 |    } | 
 | 1253 |     | 
 | 1254 |    /* Large Buffer Queue is full */ | 
 | 1255 |    if (stat_r & NS_STAT_LFBQF) | 
 | 1256 |    { | 
 | 1257 |       writel(NS_STAT_LFBQF, card->membase + STAT); | 
 | 1258 |       printk("nicstar%d: Large free buffer queue is full.\n", card->index); | 
 | 1259 |    } | 
 | 1260 |  | 
 | 1261 |    /* Receive Status Queue is full */ | 
 | 1262 |    if (stat_r & NS_STAT_RSQF) | 
 | 1263 |    { | 
 | 1264 |       writel(NS_STAT_RSQF, card->membase + STAT); | 
 | 1265 |       printk("nicstar%d: RSQ full.\n", card->index); | 
 | 1266 |       process_rsq(card); | 
 | 1267 |    } | 
 | 1268 |  | 
 | 1269 |    /* Complete CS-PDU received */ | 
 | 1270 |    if (stat_r & NS_STAT_EOPDU) | 
 | 1271 |    { | 
 | 1272 |       RXPRINTK("nicstar%d: End of CS-PDU received.\n", card->index); | 
 | 1273 |       process_rsq(card); | 
 | 1274 |       writel(NS_STAT_EOPDU, card->membase + STAT); | 
 | 1275 |    } | 
 | 1276 |  | 
 | 1277 |    /* Raw cell received */ | 
 | 1278 |    if (stat_r & NS_STAT_RAWCF) | 
 | 1279 |    { | 
 | 1280 |       writel(NS_STAT_RAWCF, card->membase + STAT); | 
 | 1281 | #ifndef RCQ_SUPPORT | 
 | 1282 |       printk("nicstar%d: Raw cell received and no support yet...\n", | 
 | 1283 |              card->index); | 
 | 1284 | #endif /* RCQ_SUPPORT */ | 
 | 1285 |       /* NOTE: the following procedure may keep a raw cell pending until the | 
 | 1286 |                next interrupt. As this preliminary support is only meant to | 
 | 1287 |                avoid buffer leakage, this is not an issue. */ | 
 | 1288 |       while (readl(card->membase + RAWCT) != card->rawch) | 
 | 1289 |       { | 
 | 1290 |          ns_rcqe *rawcell; | 
 | 1291 |  | 
 | 1292 |          rawcell = (ns_rcqe *) bus_to_virt(card->rawch); | 
 | 1293 |          if (ns_rcqe_islast(rawcell)) | 
 | 1294 |          { | 
 | 1295 |             struct sk_buff *oldbuf; | 
 | 1296 |  | 
 | 1297 |             oldbuf = card->rcbuf; | 
 | 1298 |             card->rcbuf = (struct sk_buff *) ns_rcqe_nextbufhandle(rawcell); | 
 | 1299 |             card->rawch = (u32) virt_to_bus(card->rcbuf->data); | 
 | 1300 |             recycle_rx_buf(card, oldbuf); | 
 | 1301 |          } | 
 | 1302 |          else | 
 | 1303 |             card->rawch += NS_RCQE_SIZE; | 
 | 1304 |       } | 
 | 1305 |    } | 
 | 1306 |  | 
 | 1307 |    /* Small buffer queue is empty */ | 
 | 1308 |    if (stat_r & NS_STAT_SFBQE) | 
 | 1309 |    { | 
 | 1310 |       int i; | 
 | 1311 |       struct sk_buff *sb; | 
 | 1312 |  | 
 | 1313 |       writel(NS_STAT_SFBQE, card->membase + STAT); | 
 | 1314 |       printk("nicstar%d: Small free buffer queue empty.\n", | 
 | 1315 |              card->index); | 
 | 1316 |       for (i = 0; i < card->sbnr.min; i++) | 
 | 1317 |       { | 
 | 1318 |          sb = dev_alloc_skb(NS_SMSKBSIZE); | 
 | 1319 |          if (sb == NULL) | 
 | 1320 |          { | 
 | 1321 |             writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG); | 
 | 1322 |             card->efbie = 0; | 
 | 1323 |             break; | 
 | 1324 |          } | 
 | 1325 |          skb_queue_tail(&card->sbpool.queue, sb); | 
 | 1326 |          skb_reserve(sb, NS_AAL0_HEADER); | 
 | 1327 |          push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | 
 | 1328 |       } | 
 | 1329 |       card->sbfqc = i; | 
 | 1330 |       process_rsq(card); | 
 | 1331 |    } | 
 | 1332 |  | 
 | 1333 |    /* Large buffer queue empty */ | 
 | 1334 |    if (stat_r & NS_STAT_LFBQE) | 
 | 1335 |    { | 
 | 1336 |       int i; | 
 | 1337 |       struct sk_buff *lb; | 
 | 1338 |  | 
 | 1339 |       writel(NS_STAT_LFBQE, card->membase + STAT); | 
 | 1340 |       printk("nicstar%d: Large free buffer queue empty.\n", | 
 | 1341 |              card->index); | 
 | 1342 |       for (i = 0; i < card->lbnr.min; i++) | 
 | 1343 |       { | 
 | 1344 |          lb = dev_alloc_skb(NS_LGSKBSIZE); | 
 | 1345 |          if (lb == NULL) | 
 | 1346 |          { | 
 | 1347 |             writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG); | 
 | 1348 |             card->efbie = 0; | 
 | 1349 |             break; | 
 | 1350 |          } | 
 | 1351 |          skb_queue_tail(&card->lbpool.queue, lb); | 
 | 1352 |          skb_reserve(lb, NS_SMBUFSIZE); | 
 | 1353 |          push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | 
 | 1354 |       } | 
 | 1355 |       card->lbfqc = i; | 
 | 1356 |       process_rsq(card); | 
 | 1357 |    } | 
 | 1358 |  | 
 | 1359 |    /* Receive Status Queue is 7/8 full */ | 
 | 1360 |    if (stat_r & NS_STAT_RSQAF) | 
 | 1361 |    { | 
 | 1362 |       writel(NS_STAT_RSQAF, card->membase + STAT); | 
 | 1363 |       RXPRINTK("nicstar%d: RSQ almost full.\n", card->index); | 
 | 1364 |       process_rsq(card); | 
 | 1365 |    } | 
 | 1366 |     | 
 | 1367 |    spin_unlock_irqrestore(&card->int_lock, flags); | 
 | 1368 |    PRINTK("nicstar%d: end of interrupt service\n", card->index); | 
 | 1369 |    return IRQ_HANDLED; | 
 | 1370 | } | 
 | 1371 |  | 
 | 1372 |  | 
 | 1373 |  | 
 | 1374 | static int ns_open(struct atm_vcc *vcc) | 
 | 1375 | { | 
 | 1376 |    ns_dev *card; | 
 | 1377 |    vc_map *vc; | 
 | 1378 |    unsigned long tmpl, modl; | 
 | 1379 |    int tcr, tcra;	/* target cell rate, and absolute value */ | 
 | 1380 |    int n = 0;		/* Number of entries in the TST. Initialized to remove | 
 | 1381 |                            the compiler warning. */ | 
 | 1382 |    u32 u32d[4]; | 
 | 1383 |    int frscdi = 0;	/* Index of the SCD. Initialized to remove the compiler | 
 | 1384 |                            warning. How I wish compilers were clever enough to | 
 | 1385 | 			   tell which variables can truly be used | 
 | 1386 | 			   uninitialized... */ | 
 | 1387 |    int inuse;		/* tx or rx vc already in use by another vcc */ | 
 | 1388 |    short vpi = vcc->vpi; | 
 | 1389 |    int vci = vcc->vci; | 
 | 1390 |  | 
 | 1391 |    card = (ns_dev *) vcc->dev->dev_data; | 
 | 1392 |    PRINTK("nicstar%d: opening vpi.vci %d.%d \n", card->index, (int) vpi, vci); | 
 | 1393 |    if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) | 
 | 1394 |    { | 
 | 1395 |       PRINTK("nicstar%d: unsupported AAL.\n", card->index); | 
 | 1396 |       return -EINVAL; | 
 | 1397 |    } | 
 | 1398 |  | 
 | 1399 |    vc = &(card->vcmap[vpi << card->vcibits | vci]); | 
 | 1400 |    vcc->dev_data = vc; | 
 | 1401 |  | 
 | 1402 |    inuse = 0; | 
 | 1403 |    if (vcc->qos.txtp.traffic_class != ATM_NONE && vc->tx) | 
 | 1404 |       inuse = 1; | 
 | 1405 |    if (vcc->qos.rxtp.traffic_class != ATM_NONE && vc->rx) | 
 | 1406 |       inuse += 2; | 
 | 1407 |    if (inuse) | 
 | 1408 |    { | 
 | 1409 |       printk("nicstar%d: %s vci already in use.\n", card->index, | 
 | 1410 |              inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx"); | 
 | 1411 |       return -EINVAL; | 
 | 1412 |    } | 
 | 1413 |  | 
 | 1414 |    set_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1415 |  | 
 | 1416 |    /* NOTE: You are not allowed to modify an open connection's QOS. To change | 
 | 1417 |       that, remove the ATM_VF_PARTIAL flag checking. There may be other changes | 
 | 1418 |       needed to do that. */ | 
 | 1419 |    if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) | 
 | 1420 |    { | 
 | 1421 |       scq_info *scq; | 
 | 1422 |        | 
 | 1423 |       set_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1424 |       if (vcc->qos.txtp.traffic_class == ATM_CBR) | 
 | 1425 |       { | 
 | 1426 |          /* Check requested cell rate and availability of SCD */ | 
 | 1427 |          if (vcc->qos.txtp.max_pcr == 0 && vcc->qos.txtp.pcr == 0 && | 
 | 1428 |              vcc->qos.txtp.min_pcr == 0) | 
 | 1429 |          { | 
 | 1430 |             PRINTK("nicstar%d: trying to open a CBR vc with cell rate = 0 \n", | 
 | 1431 | 	           card->index); | 
 | 1432 | 	    clear_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1433 | 	    clear_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1434 |             return -EINVAL; | 
 | 1435 |          } | 
 | 1436 |  | 
 | 1437 |          tcr = atm_pcr_goal(&(vcc->qos.txtp)); | 
 | 1438 |          tcra = tcr >= 0 ? tcr : -tcr; | 
 | 1439 |        | 
 | 1440 |          PRINTK("nicstar%d: target cell rate = %d.\n", card->index, | 
 | 1441 |                 vcc->qos.txtp.max_pcr); | 
 | 1442 |  | 
 | 1443 |          tmpl = (unsigned long)tcra * (unsigned long)NS_TST_NUM_ENTRIES; | 
 | 1444 |          modl = tmpl % card->max_pcr; | 
 | 1445 |  | 
 | 1446 |          n = (int)(tmpl / card->max_pcr); | 
 | 1447 |          if (tcr > 0) | 
 | 1448 |          { | 
 | 1449 |             if (modl > 0) n++; | 
 | 1450 |          } | 
 | 1451 |          else if (tcr == 0) | 
 | 1452 |          { | 
 | 1453 |             if ((n = (card->tst_free_entries - NS_TST_RESERVED)) <= 0) | 
 | 1454 | 	    { | 
 | 1455 |                PRINTK("nicstar%d: no CBR bandwidth free.\n", card->index); | 
 | 1456 | 	       clear_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1457 | 	       clear_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1458 |                return -EINVAL; | 
 | 1459 |             } | 
 | 1460 |          } | 
 | 1461 |  | 
 | 1462 |          if (n == 0) | 
 | 1463 |          { | 
 | 1464 |             printk("nicstar%d: selected bandwidth < granularity.\n", card->index); | 
 | 1465 | 	    clear_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1466 | 	    clear_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1467 |             return -EINVAL; | 
 | 1468 |          } | 
 | 1469 |  | 
 | 1470 |          if (n > (card->tst_free_entries - NS_TST_RESERVED)) | 
 | 1471 |          { | 
 | 1472 |             PRINTK("nicstar%d: not enough free CBR bandwidth.\n", card->index); | 
 | 1473 | 	    clear_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1474 | 	    clear_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1475 |             return -EINVAL; | 
 | 1476 |          } | 
 | 1477 |          else | 
 | 1478 |             card->tst_free_entries -= n; | 
 | 1479 |  | 
 | 1480 |          XPRINTK("nicstar%d: writing %d tst entries.\n", card->index, n); | 
 | 1481 |          for (frscdi = 0; frscdi < NS_FRSCD_NUM; frscdi++) | 
 | 1482 |          { | 
 | 1483 |             if (card->scd2vc[frscdi] == NULL) | 
 | 1484 |             { | 
 | 1485 |                card->scd2vc[frscdi] = vc; | 
 | 1486 |                break; | 
 | 1487 | 	    } | 
 | 1488 |          } | 
 | 1489 |          if (frscdi == NS_FRSCD_NUM) | 
 | 1490 |          { | 
 | 1491 |             PRINTK("nicstar%d: no SCD available for CBR channel.\n", card->index); | 
 | 1492 |             card->tst_free_entries += n; | 
 | 1493 | 	    clear_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1494 | 	    clear_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1495 | 	    return -EBUSY; | 
 | 1496 |          } | 
 | 1497 |  | 
 | 1498 |          vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE; | 
 | 1499 |  | 
 | 1500 |          scq = get_scq(CBR_SCQSIZE, vc->cbr_scd); | 
| Jesper Juhl | a2c1aa5 | 2005-06-02 13:04:07 -0700 | [diff] [blame] | 1501 |          if (scq == NULL) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1502 |          { | 
 | 1503 |             PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index); | 
 | 1504 |             card->scd2vc[frscdi] = NULL; | 
 | 1505 |             card->tst_free_entries += n; | 
 | 1506 | 	    clear_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1507 | 	    clear_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1508 |             return -ENOMEM; | 
 | 1509 |          } | 
 | 1510 | 	 vc->scq = scq; | 
 | 1511 |          u32d[0] = (u32) virt_to_bus(scq->base); | 
 | 1512 |          u32d[1] = (u32) 0x00000000; | 
 | 1513 |          u32d[2] = (u32) 0xffffffff; | 
 | 1514 |          u32d[3] = (u32) 0x00000000; | 
 | 1515 |          ns_write_sram(card, vc->cbr_scd, u32d, 4); | 
 | 1516 |           | 
 | 1517 | 	 fill_tst(card, n, vc); | 
 | 1518 |       } | 
 | 1519 |       else if (vcc->qos.txtp.traffic_class == ATM_UBR) | 
 | 1520 |       { | 
 | 1521 |          vc->cbr_scd = 0x00000000; | 
 | 1522 | 	 vc->scq = card->scq0; | 
 | 1523 |       } | 
 | 1524 |        | 
 | 1525 |       if (vcc->qos.txtp.traffic_class != ATM_NONE) | 
 | 1526 |       { | 
 | 1527 |          vc->tx = 1; | 
 | 1528 | 	 vc->tx_vcc = vcc; | 
 | 1529 | 	 vc->tbd_count = 0; | 
 | 1530 |       } | 
 | 1531 |       if (vcc->qos.rxtp.traffic_class != ATM_NONE) | 
 | 1532 |       { | 
 | 1533 |          u32 status; | 
 | 1534 |        | 
 | 1535 |          vc->rx = 1; | 
 | 1536 |          vc->rx_vcc = vcc; | 
 | 1537 |          vc->rx_iov = NULL; | 
 | 1538 |  | 
 | 1539 | 	 /* Open the connection in hardware */ | 
 | 1540 | 	 if (vcc->qos.aal == ATM_AAL5) | 
 | 1541 | 	    status = NS_RCTE_AAL5 | NS_RCTE_CONNECTOPEN; | 
 | 1542 | 	 else /* vcc->qos.aal == ATM_AAL0 */ | 
 | 1543 | 	    status = NS_RCTE_AAL0 | NS_RCTE_CONNECTOPEN; | 
 | 1544 | #ifdef RCQ_SUPPORT | 
 | 1545 |          status |= NS_RCTE_RAWCELLINTEN; | 
 | 1546 | #endif /* RCQ_SUPPORT */ | 
 | 1547 |          ns_write_sram(card, NS_RCT + (vpi << card->vcibits | vci) * | 
 | 1548 | 	               NS_RCT_ENTRY_SIZE, &status, 1); | 
 | 1549 |       } | 
 | 1550 |        | 
 | 1551 |    } | 
 | 1552 |     | 
 | 1553 |    set_bit(ATM_VF_READY,&vcc->flags); | 
 | 1554 |    return 0; | 
 | 1555 | } | 
 | 1556 |  | 
 | 1557 |  | 
 | 1558 |  | 
 | 1559 | static void ns_close(struct atm_vcc *vcc) | 
 | 1560 | { | 
 | 1561 |    vc_map *vc; | 
 | 1562 |    ns_dev *card; | 
 | 1563 |    u32 data; | 
 | 1564 |    int i; | 
 | 1565 |     | 
 | 1566 |    vc = vcc->dev_data; | 
 | 1567 |    card = vcc->dev->dev_data; | 
 | 1568 |    PRINTK("nicstar%d: closing vpi.vci %d.%d \n", card->index, | 
 | 1569 |           (int) vcc->vpi, vcc->vci); | 
 | 1570 |  | 
 | 1571 |    clear_bit(ATM_VF_READY,&vcc->flags); | 
 | 1572 |     | 
 | 1573 |    if (vcc->qos.rxtp.traffic_class != ATM_NONE) | 
 | 1574 |    { | 
 | 1575 |       u32 addr; | 
 | 1576 |       unsigned long flags; | 
 | 1577 |        | 
 | 1578 |       addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE; | 
 | 1579 |       ns_grab_res_lock(card, flags); | 
 | 1580 |       while(CMD_BUSY(card)); | 
 | 1581 |       writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD); | 
 | 1582 |       spin_unlock_irqrestore(&card->res_lock, flags); | 
 | 1583 |        | 
 | 1584 |       vc->rx = 0; | 
 | 1585 |       if (vc->rx_iov != NULL) | 
 | 1586 |       { | 
 | 1587 | 	 struct sk_buff *iovb; | 
 | 1588 | 	 u32 stat; | 
 | 1589 |     | 
 | 1590 |          stat = readl(card->membase + STAT); | 
 | 1591 |          card->sbfqc = ns_stat_sfbqc_get(stat);    | 
 | 1592 |          card->lbfqc = ns_stat_lfbqc_get(stat); | 
 | 1593 |  | 
 | 1594 |          PRINTK("nicstar%d: closing a VC with pending rx buffers.\n", | 
 | 1595 | 	        card->index); | 
 | 1596 |          iovb = vc->rx_iov; | 
 | 1597 |          recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | 
 | 1598 | 	                       NS_SKB(iovb)->iovcnt); | 
 | 1599 |          NS_SKB(iovb)->iovcnt = 0; | 
 | 1600 |          NS_SKB(iovb)->vcc = NULL; | 
 | 1601 |          ns_grab_int_lock(card, flags); | 
 | 1602 |          recycle_iov_buf(card, iovb); | 
 | 1603 |          spin_unlock_irqrestore(&card->int_lock, flags); | 
 | 1604 |          vc->rx_iov = NULL; | 
 | 1605 |       } | 
 | 1606 |    } | 
 | 1607 |  | 
 | 1608 |    if (vcc->qos.txtp.traffic_class != ATM_NONE) | 
 | 1609 |    { | 
 | 1610 |       vc->tx = 0; | 
 | 1611 |    } | 
 | 1612 |  | 
 | 1613 |    if (vcc->qos.txtp.traffic_class == ATM_CBR) | 
 | 1614 |    { | 
 | 1615 |       unsigned long flags; | 
 | 1616 |       ns_scqe *scqep; | 
 | 1617 |       scq_info *scq; | 
 | 1618 |  | 
 | 1619 |       scq = vc->scq; | 
 | 1620 |  | 
 | 1621 |       for (;;) | 
 | 1622 |       { | 
 | 1623 |          ns_grab_scq_lock(card, scq, flags); | 
 | 1624 |          scqep = scq->next; | 
 | 1625 |          if (scqep == scq->base) | 
 | 1626 |             scqep = scq->last; | 
 | 1627 |          else | 
 | 1628 |             scqep--; | 
 | 1629 |          if (scqep == scq->tail) | 
 | 1630 |          { | 
 | 1631 |             spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1632 |             break; | 
 | 1633 |          } | 
 | 1634 |          /* If the last entry is not a TSR, place one in the SCQ in order to | 
 | 1635 |             be able to completely drain it and then close. */ | 
 | 1636 |          if (!ns_scqe_is_tsr(scqep) && scq->tail != scq->next) | 
 | 1637 |          { | 
 | 1638 |             ns_scqe tsr; | 
 | 1639 |             u32 scdi, scqi; | 
 | 1640 |             u32 data; | 
 | 1641 |             int index; | 
 | 1642 |  | 
 | 1643 |             tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); | 
 | 1644 |             scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; | 
 | 1645 |             scqi = scq->next - scq->base; | 
 | 1646 |             tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); | 
 | 1647 |             tsr.word_3 = 0x00000000; | 
 | 1648 |             tsr.word_4 = 0x00000000; | 
 | 1649 |             *scq->next = tsr; | 
 | 1650 |             index = (int) scqi; | 
 | 1651 |             scq->skb[index] = NULL; | 
 | 1652 |             if (scq->next == scq->last) | 
 | 1653 |                scq->next = scq->base; | 
 | 1654 |             else | 
 | 1655 |                scq->next++; | 
 | 1656 |             data = (u32) virt_to_bus(scq->next); | 
 | 1657 |             ns_write_sram(card, scq->scd, &data, 1); | 
 | 1658 |          } | 
 | 1659 |          spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1660 |          schedule(); | 
 | 1661 |       } | 
 | 1662 |  | 
 | 1663 |       /* Free all TST entries */ | 
 | 1664 |       data = NS_TST_OPCODE_VARIABLE; | 
 | 1665 |       for (i = 0; i < NS_TST_NUM_ENTRIES; i++) | 
 | 1666 |       { | 
 | 1667 |          if (card->tste2vc[i] == vc) | 
 | 1668 | 	 { | 
 | 1669 |             ns_write_sram(card, card->tst_addr + i, &data, 1); | 
 | 1670 |             card->tste2vc[i] = NULL; | 
 | 1671 |             card->tst_free_entries++; | 
 | 1672 | 	 } | 
 | 1673 |       } | 
 | 1674 |        | 
 | 1675 |       card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL; | 
 | 1676 |       free_scq(vc->scq, vcc); | 
 | 1677 |    } | 
 | 1678 |  | 
 | 1679 |    /* remove all references to vcc before deleting it */ | 
 | 1680 |    if (vcc->qos.txtp.traffic_class != ATM_NONE) | 
 | 1681 |    { | 
 | 1682 |      unsigned long flags; | 
 | 1683 |      scq_info *scq = card->scq0; | 
 | 1684 |  | 
 | 1685 |      ns_grab_scq_lock(card, scq, flags); | 
 | 1686 |  | 
 | 1687 |      for(i = 0; i < scq->num_entries; i++) { | 
 | 1688 |        if(scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) { | 
 | 1689 |         ATM_SKB(scq->skb[i])->vcc = NULL; | 
 | 1690 | 	atm_return(vcc, scq->skb[i]->truesize); | 
 | 1691 |         PRINTK("nicstar: deleted pending vcc mapping\n"); | 
 | 1692 |        } | 
 | 1693 |      } | 
 | 1694 |  | 
 | 1695 |      spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1696 |    } | 
 | 1697 |  | 
 | 1698 |    vcc->dev_data = NULL; | 
 | 1699 |    clear_bit(ATM_VF_PARTIAL,&vcc->flags); | 
 | 1700 |    clear_bit(ATM_VF_ADDR,&vcc->flags); | 
 | 1701 |  | 
 | 1702 | #ifdef RX_DEBUG | 
 | 1703 |    { | 
 | 1704 |       u32 stat, cfg; | 
 | 1705 |       stat = readl(card->membase + STAT); | 
 | 1706 |       cfg = readl(card->membase + CFG); | 
 | 1707 |       printk("STAT = 0x%08X  CFG = 0x%08X  \n", stat, cfg); | 
 | 1708 |       printk("TSQ: base = 0x%08X  next = 0x%08X  last = 0x%08X  TSQT = 0x%08X \n", | 
 | 1709 |              (u32) card->tsq.base, (u32) card->tsq.next,(u32) card->tsq.last, | 
 | 1710 | 	     readl(card->membase + TSQT)); | 
 | 1711 |       printk("RSQ: base = 0x%08X  next = 0x%08X  last = 0x%08X  RSQT = 0x%08X \n", | 
 | 1712 |              (u32) card->rsq.base, (u32) card->rsq.next,(u32) card->rsq.last, | 
 | 1713 | 	     readl(card->membase + RSQT)); | 
 | 1714 |       printk("Empty free buffer queue interrupt %s \n", | 
 | 1715 |              card->efbie ? "enabled" : "disabled"); | 
 | 1716 |       printk("SBCNT = %d  count = %d   LBCNT = %d count = %d \n", | 
 | 1717 |              ns_stat_sfbqc_get(stat), card->sbpool.count, | 
 | 1718 | 	     ns_stat_lfbqc_get(stat), card->lbpool.count); | 
 | 1719 |       printk("hbpool.count = %d  iovpool.count = %d \n", | 
 | 1720 |              card->hbpool.count, card->iovpool.count); | 
 | 1721 |    } | 
 | 1722 | #endif /* RX_DEBUG */ | 
 | 1723 | } | 
 | 1724 |  | 
 | 1725 |  | 
 | 1726 |  | 
 | 1727 | static void fill_tst(ns_dev *card, int n, vc_map *vc) | 
 | 1728 | { | 
 | 1729 |    u32 new_tst; | 
 | 1730 |    unsigned long cl; | 
 | 1731 |    int e, r; | 
 | 1732 |    u32 data; | 
 | 1733 |        | 
 | 1734 |    /* It would be very complicated to keep the two TSTs synchronized while | 
 | 1735 |       assuring that writes are only made to the inactive TST. So, for now I | 
 | 1736 |       will use only one TST. If problems occur, I will change this again */ | 
 | 1737 |     | 
 | 1738 |    new_tst = card->tst_addr; | 
 | 1739 |  | 
 | 1740 |    /* Fill procedure */ | 
 | 1741 |  | 
 | 1742 |    for (e = 0; e < NS_TST_NUM_ENTRIES; e++) | 
 | 1743 |    { | 
 | 1744 |       if (card->tste2vc[e] == NULL) | 
 | 1745 |          break; | 
 | 1746 |    } | 
 | 1747 |    if (e == NS_TST_NUM_ENTRIES) { | 
 | 1748 |       printk("nicstar%d: No free TST entries found. \n", card->index); | 
 | 1749 |       return; | 
 | 1750 |    } | 
 | 1751 |  | 
 | 1752 |    r = n; | 
 | 1753 |    cl = NS_TST_NUM_ENTRIES; | 
 | 1754 |    data = ns_tste_make(NS_TST_OPCODE_FIXED, vc->cbr_scd); | 
 | 1755 |        | 
 | 1756 |    while (r > 0) | 
 | 1757 |    { | 
 | 1758 |       if (cl >= NS_TST_NUM_ENTRIES && card->tste2vc[e] == NULL) | 
 | 1759 |       { | 
 | 1760 |          card->tste2vc[e] = vc; | 
 | 1761 |          ns_write_sram(card, new_tst + e, &data, 1); | 
 | 1762 |          cl -= NS_TST_NUM_ENTRIES; | 
 | 1763 |          r--; | 
 | 1764 |       } | 
 | 1765 |  | 
 | 1766 |       if (++e == NS_TST_NUM_ENTRIES) { | 
 | 1767 |          e = 0; | 
 | 1768 |       } | 
 | 1769 |       cl += n; | 
 | 1770 |    } | 
 | 1771 |     | 
 | 1772 |    /* End of fill procedure */ | 
 | 1773 |     | 
 | 1774 |    data = ns_tste_make(NS_TST_OPCODE_END, new_tst); | 
 | 1775 |    ns_write_sram(card, new_tst + NS_TST_NUM_ENTRIES, &data, 1); | 
 | 1776 |    ns_write_sram(card, card->tst_addr + NS_TST_NUM_ENTRIES, &data, 1); | 
 | 1777 |    card->tst_addr = new_tst; | 
 | 1778 | } | 
 | 1779 |  | 
 | 1780 |  | 
 | 1781 |  | 
 | 1782 | static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) | 
 | 1783 | { | 
 | 1784 |    ns_dev *card; | 
 | 1785 |    vc_map *vc; | 
 | 1786 |    scq_info *scq; | 
 | 1787 |    unsigned long buflen; | 
 | 1788 |    ns_scqe scqe; | 
 | 1789 |    u32 flags;		/* TBD flags, not CPU flags */ | 
 | 1790 |     | 
 | 1791 |    card = vcc->dev->dev_data; | 
 | 1792 |    TXPRINTK("nicstar%d: ns_send() called.\n", card->index); | 
 | 1793 |    if ((vc = (vc_map *) vcc->dev_data) == NULL) | 
 | 1794 |    { | 
 | 1795 |       printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n", card->index); | 
 | 1796 |       atomic_inc(&vcc->stats->tx_err); | 
 | 1797 |       dev_kfree_skb_any(skb); | 
 | 1798 |       return -EINVAL; | 
 | 1799 |    } | 
 | 1800 |     | 
 | 1801 |    if (!vc->tx) | 
 | 1802 |    { | 
 | 1803 |       printk("nicstar%d: Trying to transmit on a non-tx VC.\n", card->index); | 
 | 1804 |       atomic_inc(&vcc->stats->tx_err); | 
 | 1805 |       dev_kfree_skb_any(skb); | 
 | 1806 |       return -EINVAL; | 
 | 1807 |    } | 
 | 1808 |     | 
 | 1809 |    if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) | 
 | 1810 |    { | 
 | 1811 |       printk("nicstar%d: Only AAL0 and AAL5 are supported.\n", card->index); | 
 | 1812 |       atomic_inc(&vcc->stats->tx_err); | 
 | 1813 |       dev_kfree_skb_any(skb); | 
 | 1814 |       return -EINVAL; | 
 | 1815 |    } | 
 | 1816 |     | 
 | 1817 |    if (skb_shinfo(skb)->nr_frags != 0) | 
 | 1818 |    { | 
 | 1819 |       printk("nicstar%d: No scatter-gather yet.\n", card->index); | 
 | 1820 |       atomic_inc(&vcc->stats->tx_err); | 
 | 1821 |       dev_kfree_skb_any(skb); | 
 | 1822 |       return -EINVAL; | 
 | 1823 |    } | 
 | 1824 |     | 
 | 1825 |    ATM_SKB(skb)->vcc = vcc; | 
 | 1826 |  | 
 | 1827 |    if (vcc->qos.aal == ATM_AAL5) | 
 | 1828 |    { | 
 | 1829 |       buflen = (skb->len + 47 + 8) / 48 * 48;	/* Multiple of 48 */ | 
 | 1830 |       flags = NS_TBD_AAL5; | 
 | 1831 |       scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data)); | 
 | 1832 |       scqe.word_3 = cpu_to_le32((u32) skb->len); | 
 | 1833 |       scqe.word_4 = ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0, | 
 | 1834 |                            ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? 1 : 0); | 
 | 1835 |       flags |= NS_TBD_EOPDU; | 
 | 1836 |    } | 
 | 1837 |    else /* (vcc->qos.aal == ATM_AAL0) */ | 
 | 1838 |    { | 
 | 1839 |       buflen = ATM_CELL_PAYLOAD;	/* i.e., 48 bytes */ | 
 | 1840 |       flags = NS_TBD_AAL0; | 
 | 1841 |       scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data) + NS_AAL0_HEADER); | 
 | 1842 |       scqe.word_3 = cpu_to_le32(0x00000000); | 
 | 1843 |       if (*skb->data & 0x02)	/* Payload type 1 - end of pdu */ | 
 | 1844 |          flags |= NS_TBD_EOPDU; | 
 | 1845 |       scqe.word_4 = cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK); | 
 | 1846 |       /* Force the VPI/VCI to be the same as in VCC struct */ | 
 | 1847 |       scqe.word_4 |= cpu_to_le32((((u32) vcc->vpi) << NS_TBD_VPI_SHIFT | | 
 | 1848 |                                  ((u32) vcc->vci) << NS_TBD_VCI_SHIFT) & | 
 | 1849 |                                  NS_TBD_VC_MASK); | 
 | 1850 |    } | 
 | 1851 |  | 
 | 1852 |    if (vcc->qos.txtp.traffic_class == ATM_CBR) | 
 | 1853 |    { | 
 | 1854 |       scqe.word_1 = ns_tbd_mkword_1_novbr(flags, (u32) buflen); | 
 | 1855 |       scq = ((vc_map *) vcc->dev_data)->scq; | 
 | 1856 |    } | 
 | 1857 |    else | 
 | 1858 |    { | 
 | 1859 |       scqe.word_1 = ns_tbd_mkword_1(flags, (u32) 1, (u32) 1, (u32) buflen); | 
 | 1860 |       scq = card->scq0; | 
 | 1861 |    } | 
 | 1862 |  | 
 | 1863 |    if (push_scqe(card, vc, scq, &scqe, skb) != 0) | 
 | 1864 |    { | 
 | 1865 |       atomic_inc(&vcc->stats->tx_err); | 
 | 1866 |       dev_kfree_skb_any(skb); | 
 | 1867 |       return -EIO; | 
 | 1868 |    } | 
 | 1869 |    atomic_inc(&vcc->stats->tx); | 
 | 1870 |  | 
 | 1871 |    return 0; | 
 | 1872 | } | 
 | 1873 |  | 
 | 1874 |  | 
 | 1875 |  | 
 | 1876 | static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, | 
 | 1877 |                      struct sk_buff *skb) | 
 | 1878 | { | 
 | 1879 |    unsigned long flags; | 
 | 1880 |    ns_scqe tsr; | 
 | 1881 |    u32 scdi, scqi; | 
 | 1882 |    int scq_is_vbr; | 
 | 1883 |    u32 data; | 
 | 1884 |    int index; | 
 | 1885 |     | 
 | 1886 |    ns_grab_scq_lock(card, scq, flags); | 
 | 1887 |    while (scq->tail == scq->next) | 
 | 1888 |    { | 
 | 1889 |       if (in_interrupt()) { | 
 | 1890 |          spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1891 |          printk("nicstar%d: Error pushing TBD.\n", card->index); | 
 | 1892 |          return 1; | 
 | 1893 |       } | 
 | 1894 |  | 
 | 1895 |       scq->full = 1; | 
 | 1896 |       spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1897 |       interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); | 
 | 1898 |       ns_grab_scq_lock(card, scq, flags); | 
 | 1899 |  | 
 | 1900 |       if (scq->full) { | 
 | 1901 |          spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1902 |          printk("nicstar%d: Timeout pushing TBD.\n", card->index); | 
 | 1903 |          return 1; | 
 | 1904 |       } | 
 | 1905 |    } | 
 | 1906 |    *scq->next = *tbd; | 
 | 1907 |    index = (int) (scq->next - scq->base); | 
 | 1908 |    scq->skb[index] = skb; | 
 | 1909 |    XPRINTK("nicstar%d: sending skb at 0x%x (pos %d).\n", | 
 | 1910 |            card->index, (u32) skb, index); | 
 | 1911 |    XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", | 
 | 1912 |            card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2), | 
 | 1913 |            le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4), | 
 | 1914 |            (u32) scq->next); | 
 | 1915 |    if (scq->next == scq->last) | 
 | 1916 |       scq->next = scq->base; | 
 | 1917 |    else | 
 | 1918 |       scq->next++; | 
 | 1919 |  | 
 | 1920 |    vc->tbd_count++; | 
 | 1921 |    if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) | 
 | 1922 |    { | 
 | 1923 |       scq->tbd_count++; | 
 | 1924 |       scq_is_vbr = 1; | 
 | 1925 |    } | 
 | 1926 |    else | 
 | 1927 |       scq_is_vbr = 0; | 
 | 1928 |  | 
 | 1929 |    if (vc->tbd_count >= MAX_TBD_PER_VC || scq->tbd_count >= MAX_TBD_PER_SCQ) | 
 | 1930 |    { | 
 | 1931 |       int has_run = 0; | 
 | 1932 |  | 
 | 1933 |       while (scq->tail == scq->next) | 
 | 1934 |       { | 
 | 1935 |          if (in_interrupt()) { | 
 | 1936 |             data = (u32) virt_to_bus(scq->next); | 
 | 1937 |             ns_write_sram(card, scq->scd, &data, 1); | 
 | 1938 |             spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1939 |             printk("nicstar%d: Error pushing TSR.\n", card->index); | 
 | 1940 |             return 0; | 
 | 1941 |          } | 
 | 1942 |  | 
 | 1943 |          scq->full = 1; | 
 | 1944 |          if (has_run++) break; | 
 | 1945 |          spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1946 |          interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); | 
 | 1947 |          ns_grab_scq_lock(card, scq, flags); | 
 | 1948 |       } | 
 | 1949 |  | 
 | 1950 |       if (!scq->full) | 
 | 1951 |       { | 
 | 1952 |          tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); | 
 | 1953 |          if (scq_is_vbr) | 
 | 1954 |             scdi = NS_TSR_SCDISVBR; | 
 | 1955 |          else | 
 | 1956 |             scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; | 
 | 1957 |          scqi = scq->next - scq->base; | 
 | 1958 |          tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); | 
 | 1959 |          tsr.word_3 = 0x00000000; | 
 | 1960 |          tsr.word_4 = 0x00000000; | 
 | 1961 |  | 
 | 1962 |          *scq->next = tsr; | 
 | 1963 |          index = (int) scqi; | 
 | 1964 |          scq->skb[index] = NULL; | 
 | 1965 |          XPRINTK("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", | 
 | 1966 |                  card->index, le32_to_cpu(tsr.word_1), le32_to_cpu(tsr.word_2), | 
 | 1967 |                  le32_to_cpu(tsr.word_3), le32_to_cpu(tsr.word_4), | 
 | 1968 | 		 (u32) scq->next); | 
 | 1969 |          if (scq->next == scq->last) | 
 | 1970 |             scq->next = scq->base; | 
 | 1971 |          else | 
 | 1972 |             scq->next++; | 
 | 1973 |          vc->tbd_count = 0; | 
 | 1974 |          scq->tbd_count = 0; | 
 | 1975 |       } | 
 | 1976 |       else | 
 | 1977 |          PRINTK("nicstar%d: Timeout pushing TSR.\n", card->index); | 
 | 1978 |    } | 
 | 1979 |    data = (u32) virt_to_bus(scq->next); | 
 | 1980 |    ns_write_sram(card, scq->scd, &data, 1); | 
 | 1981 |     | 
 | 1982 |    spin_unlock_irqrestore(&scq->lock, flags); | 
 | 1983 |     | 
 | 1984 |    return 0; | 
 | 1985 | } | 
 | 1986 |  | 
 | 1987 |  | 
 | 1988 |  | 
 | 1989 | static void process_tsq(ns_dev *card) | 
 | 1990 | { | 
 | 1991 |    u32 scdi; | 
 | 1992 |    scq_info *scq; | 
 | 1993 |    ns_tsi *previous = NULL, *one_ahead, *two_ahead; | 
 | 1994 |    int serviced_entries;   /* flag indicating at least on entry was serviced */ | 
 | 1995 |     | 
 | 1996 |    serviced_entries = 0; | 
 | 1997 |     | 
 | 1998 |    if (card->tsq.next == card->tsq.last) | 
 | 1999 |       one_ahead = card->tsq.base; | 
 | 2000 |    else | 
 | 2001 |       one_ahead = card->tsq.next + 1; | 
 | 2002 |  | 
 | 2003 |    if (one_ahead == card->tsq.last) | 
 | 2004 |       two_ahead = card->tsq.base; | 
 | 2005 |    else | 
 | 2006 |       two_ahead = one_ahead + 1; | 
 | 2007 |     | 
 | 2008 |    while (!ns_tsi_isempty(card->tsq.next) || !ns_tsi_isempty(one_ahead) || | 
 | 2009 |           !ns_tsi_isempty(two_ahead)) | 
 | 2010 |           /* At most two empty, as stated in the 77201 errata */ | 
 | 2011 |    { | 
 | 2012 |       serviced_entries = 1; | 
 | 2013 |      | 
 | 2014 |       /* Skip the one or two possible empty entries */ | 
 | 2015 |       while (ns_tsi_isempty(card->tsq.next)) { | 
 | 2016 |          if (card->tsq.next == card->tsq.last) | 
 | 2017 |             card->tsq.next = card->tsq.base; | 
 | 2018 |          else | 
 | 2019 |             card->tsq.next++; | 
 | 2020 |       } | 
 | 2021 |      | 
 | 2022 |       if (!ns_tsi_tmrof(card->tsq.next)) | 
 | 2023 |       { | 
 | 2024 |          scdi = ns_tsi_getscdindex(card->tsq.next); | 
 | 2025 | 	 if (scdi == NS_TSI_SCDISVBR) | 
 | 2026 | 	    scq = card->scq0; | 
 | 2027 | 	 else | 
 | 2028 | 	 { | 
 | 2029 | 	    if (card->scd2vc[scdi] == NULL) | 
 | 2030 | 	    { | 
 | 2031 | 	       printk("nicstar%d: could not find VC from SCD index.\n", | 
 | 2032 | 	              card->index); | 
 | 2033 |                ns_tsi_init(card->tsq.next); | 
 | 2034 |                return; | 
 | 2035 |             } | 
 | 2036 |             scq = card->scd2vc[scdi]->scq; | 
 | 2037 |          } | 
 | 2038 |          drain_scq(card, scq, ns_tsi_getscqpos(card->tsq.next)); | 
 | 2039 |          scq->full = 0; | 
 | 2040 |          wake_up_interruptible(&(scq->scqfull_waitq)); | 
 | 2041 |       } | 
 | 2042 |  | 
 | 2043 |       ns_tsi_init(card->tsq.next); | 
 | 2044 |       previous = card->tsq.next; | 
 | 2045 |       if (card->tsq.next == card->tsq.last) | 
 | 2046 |          card->tsq.next = card->tsq.base; | 
 | 2047 |       else | 
 | 2048 |          card->tsq.next++; | 
 | 2049 |  | 
 | 2050 |       if (card->tsq.next == card->tsq.last) | 
 | 2051 |          one_ahead = card->tsq.base; | 
 | 2052 |       else | 
 | 2053 |          one_ahead = card->tsq.next + 1; | 
 | 2054 |  | 
 | 2055 |       if (one_ahead == card->tsq.last) | 
 | 2056 |          two_ahead = card->tsq.base; | 
 | 2057 |       else | 
 | 2058 |          two_ahead = one_ahead + 1; | 
 | 2059 |    } | 
 | 2060 |  | 
 | 2061 |    if (serviced_entries) { | 
 | 2062 |       writel((((u32) previous) - ((u32) card->tsq.base)), | 
 | 2063 |              card->membase + TSQH); | 
 | 2064 |    } | 
 | 2065 | } | 
 | 2066 |  | 
 | 2067 |  | 
 | 2068 |  | 
 | 2069 | static void drain_scq(ns_dev *card, scq_info *scq, int pos) | 
 | 2070 | { | 
 | 2071 |    struct atm_vcc *vcc; | 
 | 2072 |    struct sk_buff *skb; | 
 | 2073 |    int i; | 
 | 2074 |    unsigned long flags; | 
 | 2075 |     | 
 | 2076 |    XPRINTK("nicstar%d: drain_scq() called, scq at 0x%x, pos %d.\n", | 
 | 2077 |            card->index, (u32) scq, pos); | 
 | 2078 |    if (pos >= scq->num_entries) | 
 | 2079 |    { | 
 | 2080 |       printk("nicstar%d: Bad index on drain_scq().\n", card->index); | 
 | 2081 |       return; | 
 | 2082 |    } | 
 | 2083 |  | 
 | 2084 |    ns_grab_scq_lock(card, scq, flags); | 
 | 2085 |    i = (int) (scq->tail - scq->base); | 
 | 2086 |    if (++i == scq->num_entries) | 
 | 2087 |       i = 0; | 
 | 2088 |    while (i != pos) | 
 | 2089 |    { | 
 | 2090 |       skb = scq->skb[i]; | 
 | 2091 |       XPRINTK("nicstar%d: freeing skb at 0x%x (index %d).\n", | 
 | 2092 |               card->index, (u32) skb, i); | 
 | 2093 |       if (skb != NULL) | 
 | 2094 |       { | 
 | 2095 |          vcc = ATM_SKB(skb)->vcc; | 
 | 2096 | 	 if (vcc && vcc->pop != NULL) { | 
 | 2097 | 	    vcc->pop(vcc, skb); | 
 | 2098 | 	 } else { | 
 | 2099 | 	    dev_kfree_skb_irq(skb); | 
 | 2100 |          } | 
 | 2101 | 	 scq->skb[i] = NULL; | 
 | 2102 |       } | 
 | 2103 |       if (++i == scq->num_entries) | 
 | 2104 |          i = 0; | 
 | 2105 |    } | 
 | 2106 |    scq->tail = scq->base + pos; | 
 | 2107 |    spin_unlock_irqrestore(&scq->lock, flags); | 
 | 2108 | } | 
 | 2109 |  | 
 | 2110 |  | 
 | 2111 |  | 
 | 2112 | static void process_rsq(ns_dev *card) | 
 | 2113 | { | 
 | 2114 |    ns_rsqe *previous; | 
 | 2115 |  | 
 | 2116 |    if (!ns_rsqe_valid(card->rsq.next)) | 
 | 2117 |       return; | 
 | 2118 |    while (ns_rsqe_valid(card->rsq.next)) | 
 | 2119 |    { | 
 | 2120 |       dequeue_rx(card, card->rsq.next); | 
 | 2121 |       ns_rsqe_init(card->rsq.next); | 
 | 2122 |       previous = card->rsq.next; | 
 | 2123 |       if (card->rsq.next == card->rsq.last) | 
 | 2124 |          card->rsq.next = card->rsq.base; | 
 | 2125 |       else | 
 | 2126 |          card->rsq.next++; | 
 | 2127 |    } | 
 | 2128 |    writel((((u32) previous) - ((u32) card->rsq.base)), | 
 | 2129 |           card->membase + RSQH); | 
 | 2130 | } | 
 | 2131 |  | 
 | 2132 |  | 
 | 2133 |  | 
 | 2134 | static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) | 
 | 2135 | { | 
 | 2136 |    u32 vpi, vci; | 
 | 2137 |    vc_map *vc; | 
 | 2138 |    struct sk_buff *iovb; | 
 | 2139 |    struct iovec *iov; | 
 | 2140 |    struct atm_vcc *vcc; | 
 | 2141 |    struct sk_buff *skb; | 
 | 2142 |    unsigned short aal5_len; | 
 | 2143 |    int len; | 
 | 2144 |    u32 stat; | 
 | 2145 |  | 
 | 2146 |    stat = readl(card->membase + STAT); | 
 | 2147 |    card->sbfqc = ns_stat_sfbqc_get(stat);    | 
 | 2148 |    card->lbfqc = ns_stat_lfbqc_get(stat); | 
 | 2149 |  | 
 | 2150 |    skb = (struct sk_buff *) le32_to_cpu(rsqe->buffer_handle); | 
 | 2151 |    vpi = ns_rsqe_vpi(rsqe); | 
 | 2152 |    vci = ns_rsqe_vci(rsqe); | 
 | 2153 |    if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) | 
 | 2154 |    { | 
 | 2155 |       printk("nicstar%d: SDU received for out-of-range vc %d.%d.\n", | 
 | 2156 |              card->index, vpi, vci); | 
 | 2157 |       recycle_rx_buf(card, skb); | 
 | 2158 |       return; | 
 | 2159 |    } | 
 | 2160 |     | 
 | 2161 |    vc = &(card->vcmap[vpi << card->vcibits | vci]); | 
 | 2162 |    if (!vc->rx) | 
 | 2163 |    { | 
 | 2164 |       RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n", | 
 | 2165 |              card->index, vpi, vci); | 
 | 2166 |       recycle_rx_buf(card, skb); | 
 | 2167 |       return; | 
 | 2168 |    } | 
 | 2169 |  | 
 | 2170 |    vcc = vc->rx_vcc; | 
 | 2171 |  | 
 | 2172 |    if (vcc->qos.aal == ATM_AAL0) | 
 | 2173 |    { | 
 | 2174 |       struct sk_buff *sb; | 
 | 2175 |       unsigned char *cell; | 
 | 2176 |       int i; | 
 | 2177 |  | 
 | 2178 |       cell = skb->data; | 
 | 2179 |       for (i = ns_rsqe_cellcount(rsqe); i; i--) | 
 | 2180 |       { | 
 | 2181 |          if ((sb = dev_alloc_skb(NS_SMSKBSIZE)) == NULL) | 
 | 2182 |          { | 
 | 2183 |             printk("nicstar%d: Can't allocate buffers for aal0.\n", | 
 | 2184 |                    card->index); | 
 | 2185 |             atomic_add(i,&vcc->stats->rx_drop); | 
 | 2186 |             break; | 
 | 2187 |          } | 
 | 2188 |          if (!atm_charge(vcc, sb->truesize)) | 
 | 2189 |          { | 
 | 2190 |             RXPRINTK("nicstar%d: atm_charge() dropped aal0 packets.\n", | 
 | 2191 |                      card->index); | 
 | 2192 |             atomic_add(i-1,&vcc->stats->rx_drop); /* already increased by 1 */ | 
 | 2193 |             dev_kfree_skb_any(sb); | 
 | 2194 |             break; | 
 | 2195 |          } | 
 | 2196 |          /* Rebuild the header */ | 
 | 2197 |          *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 | | 
 | 2198 |                                (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000); | 
 | 2199 |          if (i == 1 && ns_rsqe_eopdu(rsqe)) | 
 | 2200 |             *((u32 *) sb->data) |= 0x00000002; | 
 | 2201 |          skb_put(sb, NS_AAL0_HEADER); | 
 | 2202 |          memcpy(sb->tail, cell, ATM_CELL_PAYLOAD); | 
 | 2203 |          skb_put(sb, ATM_CELL_PAYLOAD); | 
 | 2204 |          ATM_SKB(sb)->vcc = vcc; | 
 | 2205 |          do_gettimeofday(&sb->stamp); | 
 | 2206 |          vcc->push(vcc, sb); | 
 | 2207 |          atomic_inc(&vcc->stats->rx); | 
 | 2208 |          cell += ATM_CELL_PAYLOAD; | 
 | 2209 |       } | 
 | 2210 |  | 
 | 2211 |       recycle_rx_buf(card, skb); | 
 | 2212 |       return; | 
 | 2213 |    } | 
 | 2214 |  | 
 | 2215 |    /* To reach this point, the AAL layer can only be AAL5 */ | 
 | 2216 |  | 
 | 2217 |    if ((iovb = vc->rx_iov) == NULL) | 
 | 2218 |    { | 
 | 2219 |       iovb = skb_dequeue(&(card->iovpool.queue)); | 
 | 2220 |       if (iovb == NULL)		/* No buffers in the queue */ | 
 | 2221 |       { | 
 | 2222 |          iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC); | 
 | 2223 | 	 if (iovb == NULL) | 
 | 2224 | 	 { | 
 | 2225 | 	    printk("nicstar%d: Out of iovec buffers.\n", card->index); | 
 | 2226 |             atomic_inc(&vcc->stats->rx_drop); | 
 | 2227 |             recycle_rx_buf(card, skb); | 
 | 2228 |             return; | 
 | 2229 | 	 } | 
 | 2230 |       } | 
 | 2231 |       else | 
 | 2232 |          if (--card->iovpool.count < card->iovnr.min) | 
 | 2233 | 	 { | 
 | 2234 | 	    struct sk_buff *new_iovb; | 
 | 2235 | 	    if ((new_iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL) | 
 | 2236 | 	    { | 
 | 2237 |                skb_queue_tail(&card->iovpool.queue, new_iovb); | 
 | 2238 |                card->iovpool.count++; | 
 | 2239 | 	    } | 
 | 2240 | 	 } | 
 | 2241 |       vc->rx_iov = iovb; | 
 | 2242 |       NS_SKB(iovb)->iovcnt = 0; | 
 | 2243 |       iovb->len = 0; | 
 | 2244 |       iovb->tail = iovb->data = iovb->head; | 
 | 2245 |       NS_SKB(iovb)->vcc = vcc; | 
 | 2246 |       /* IMPORTANT: a pointer to the sk_buff containing the small or large | 
 | 2247 |                     buffer is stored as iovec base, NOT a pointer to the  | 
 | 2248 | 	            small or large buffer itself. */ | 
 | 2249 |    } | 
 | 2250 |    else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS) | 
 | 2251 |    { | 
 | 2252 |       printk("nicstar%d: received too big AAL5 SDU.\n", card->index); | 
 | 2253 |       atomic_inc(&vcc->stats->rx_err); | 
 | 2254 |       recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS); | 
 | 2255 |       NS_SKB(iovb)->iovcnt = 0; | 
 | 2256 |       iovb->len = 0; | 
 | 2257 |       iovb->tail = iovb->data = iovb->head; | 
 | 2258 |       NS_SKB(iovb)->vcc = vcc; | 
 | 2259 |    } | 
 | 2260 |    iov = &((struct iovec *) iovb->data)[NS_SKB(iovb)->iovcnt++]; | 
 | 2261 |    iov->iov_base = (void *) skb; | 
 | 2262 |    iov->iov_len = ns_rsqe_cellcount(rsqe) * 48; | 
 | 2263 |    iovb->len += iov->iov_len; | 
 | 2264 |  | 
 | 2265 |    if (NS_SKB(iovb)->iovcnt == 1) | 
 | 2266 |    { | 
 | 2267 |       if (skb->list != &card->sbpool.queue) | 
 | 2268 |       { | 
 | 2269 |          printk("nicstar%d: Expected a small buffer, and this is not one.\n", | 
 | 2270 | 	        card->index); | 
 | 2271 |          which_list(card, skb); | 
 | 2272 |          atomic_inc(&vcc->stats->rx_err); | 
 | 2273 |          recycle_rx_buf(card, skb); | 
 | 2274 |          vc->rx_iov = NULL; | 
 | 2275 |          recycle_iov_buf(card, iovb); | 
 | 2276 |          return; | 
 | 2277 |       } | 
 | 2278 |    } | 
 | 2279 |    else /* NS_SKB(iovb)->iovcnt >= 2 */ | 
 | 2280 |    { | 
 | 2281 |       if (skb->list != &card->lbpool.queue) | 
 | 2282 |       { | 
 | 2283 |          printk("nicstar%d: Expected a large buffer, and this is not one.\n", | 
 | 2284 | 	        card->index); | 
 | 2285 |          which_list(card, skb); | 
 | 2286 |          atomic_inc(&vcc->stats->rx_err); | 
 | 2287 |          recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | 
 | 2288 | 	                       NS_SKB(iovb)->iovcnt); | 
 | 2289 |          vc->rx_iov = NULL; | 
 | 2290 |          recycle_iov_buf(card, iovb); | 
 | 2291 | 	 return; | 
 | 2292 |       } | 
 | 2293 |    } | 
 | 2294 |  | 
 | 2295 |    if (ns_rsqe_eopdu(rsqe)) | 
 | 2296 |    { | 
 | 2297 |       /* This works correctly regardless of the endianness of the host */ | 
 | 2298 |       unsigned char *L1L2 = (unsigned char *)((u32)skb->data + | 
 | 2299 |                                               iov->iov_len - 6); | 
 | 2300 |       aal5_len = L1L2[0] << 8 | L1L2[1]; | 
 | 2301 |       len = (aal5_len == 0x0000) ? 0x10000 : aal5_len; | 
 | 2302 |       if (ns_rsqe_crcerr(rsqe) || | 
 | 2303 |           len + 8 > iovb->len || len + (47 + 8) < iovb->len) | 
 | 2304 |       { | 
 | 2305 |          printk("nicstar%d: AAL5 CRC error", card->index); | 
 | 2306 |          if (len + 8 > iovb->len || len + (47 + 8) < iovb->len) | 
 | 2307 |             printk(" - PDU size mismatch.\n"); | 
 | 2308 |          else | 
 | 2309 |             printk(".\n"); | 
 | 2310 |          atomic_inc(&vcc->stats->rx_err); | 
 | 2311 |          recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | 
 | 2312 | 	   NS_SKB(iovb)->iovcnt); | 
 | 2313 | 	 vc->rx_iov = NULL; | 
 | 2314 |          recycle_iov_buf(card, iovb); | 
 | 2315 | 	 return; | 
 | 2316 |       } | 
 | 2317 |  | 
 | 2318 |       /* By this point we (hopefully) have a complete SDU without errors. */ | 
 | 2319 |  | 
 | 2320 |       if (NS_SKB(iovb)->iovcnt == 1)	/* Just a small buffer */ | 
 | 2321 |       { | 
 | 2322 |          /* skb points to a small buffer */ | 
 | 2323 |          if (!atm_charge(vcc, skb->truesize)) | 
 | 2324 |          { | 
 | 2325 |             push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), | 
 | 2326 |                         0, 0); | 
 | 2327 |             atomic_inc(&vcc->stats->rx_drop); | 
 | 2328 |          } | 
 | 2329 |          else | 
 | 2330 | 	 { | 
 | 2331 |             skb_put(skb, len); | 
 | 2332 |             dequeue_sm_buf(card, skb); | 
 | 2333 | #ifdef NS_USE_DESTRUCTORS | 
 | 2334 |             skb->destructor = ns_sb_destructor; | 
 | 2335 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 2336 |             ATM_SKB(skb)->vcc = vcc; | 
 | 2337 |             do_gettimeofday(&skb->stamp); | 
 | 2338 |             vcc->push(vcc, skb); | 
 | 2339 |             atomic_inc(&vcc->stats->rx); | 
 | 2340 |          } | 
 | 2341 |       } | 
 | 2342 |       else if (NS_SKB(iovb)->iovcnt == 2)	/* One small plus one large buffer */ | 
 | 2343 |       { | 
 | 2344 |          struct sk_buff *sb; | 
 | 2345 |  | 
 | 2346 |          sb = (struct sk_buff *) (iov - 1)->iov_base; | 
 | 2347 |          /* skb points to a large buffer */ | 
 | 2348 |  | 
 | 2349 |          if (len <= NS_SMBUFSIZE) | 
 | 2350 | 	 { | 
 | 2351 |             if (!atm_charge(vcc, sb->truesize)) | 
 | 2352 |             { | 
 | 2353 |                push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), | 
 | 2354 |                            0, 0); | 
 | 2355 |                atomic_inc(&vcc->stats->rx_drop); | 
 | 2356 |             } | 
 | 2357 |             else | 
 | 2358 | 	    { | 
 | 2359 |                skb_put(sb, len); | 
 | 2360 |                dequeue_sm_buf(card, sb); | 
 | 2361 | #ifdef NS_USE_DESTRUCTORS | 
 | 2362 |                sb->destructor = ns_sb_destructor; | 
 | 2363 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 2364 |                ATM_SKB(sb)->vcc = vcc; | 
 | 2365 |                do_gettimeofday(&sb->stamp); | 
 | 2366 |                vcc->push(vcc, sb); | 
 | 2367 |                atomic_inc(&vcc->stats->rx); | 
 | 2368 |             } | 
 | 2369 |  | 
 | 2370 |             push_rxbufs(card, BUF_LG, (u32) skb, | 
 | 2371 | 	                   (u32) virt_to_bus(skb->data), 0, 0); | 
 | 2372 |  | 
 | 2373 | 	 } | 
 | 2374 | 	 else			/* len > NS_SMBUFSIZE, the usual case */ | 
 | 2375 | 	 { | 
 | 2376 |             if (!atm_charge(vcc, skb->truesize)) | 
 | 2377 |             { | 
 | 2378 |                push_rxbufs(card, BUF_LG, (u32) skb, | 
 | 2379 |                            (u32) virt_to_bus(skb->data), 0, 0); | 
 | 2380 |                atomic_inc(&vcc->stats->rx_drop); | 
 | 2381 |             } | 
 | 2382 |             else | 
 | 2383 |             { | 
 | 2384 |                dequeue_lg_buf(card, skb); | 
 | 2385 | #ifdef NS_USE_DESTRUCTORS | 
 | 2386 |                skb->destructor = ns_lb_destructor; | 
 | 2387 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 2388 |                skb_push(skb, NS_SMBUFSIZE); | 
 | 2389 |                memcpy(skb->data, sb->data, NS_SMBUFSIZE); | 
 | 2390 |                skb_put(skb, len - NS_SMBUFSIZE); | 
 | 2391 |                ATM_SKB(skb)->vcc = vcc; | 
 | 2392 |                do_gettimeofday(&skb->stamp); | 
 | 2393 |                vcc->push(vcc, skb); | 
 | 2394 |                atomic_inc(&vcc->stats->rx); | 
 | 2395 |             } | 
 | 2396 |  | 
 | 2397 |             push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), | 
 | 2398 |                         0, 0); | 
 | 2399 |  | 
 | 2400 |          } | 
 | 2401 | 	  | 
 | 2402 |       } | 
 | 2403 |       else				/* Must push a huge buffer */ | 
 | 2404 |       { | 
 | 2405 |          struct sk_buff *hb, *sb, *lb; | 
 | 2406 | 	 int remaining, tocopy; | 
 | 2407 |          int j; | 
 | 2408 |  | 
 | 2409 |          hb = skb_dequeue(&(card->hbpool.queue)); | 
 | 2410 |          if (hb == NULL)		/* No buffers in the queue */ | 
 | 2411 |          { | 
 | 2412 |  | 
 | 2413 |             hb = dev_alloc_skb(NS_HBUFSIZE); | 
 | 2414 |             if (hb == NULL) | 
 | 2415 |             { | 
 | 2416 |                printk("nicstar%d: Out of huge buffers.\n", card->index); | 
 | 2417 |                atomic_inc(&vcc->stats->rx_drop); | 
 | 2418 |                recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | 
 | 2419 | 	                             NS_SKB(iovb)->iovcnt); | 
 | 2420 |                vc->rx_iov = NULL; | 
 | 2421 |                recycle_iov_buf(card, iovb); | 
 | 2422 |                return; | 
 | 2423 |             } | 
 | 2424 |             else if (card->hbpool.count < card->hbnr.min) | 
 | 2425 | 	    { | 
 | 2426 |                struct sk_buff *new_hb; | 
 | 2427 |                if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) | 
 | 2428 |                { | 
 | 2429 |                   skb_queue_tail(&card->hbpool.queue, new_hb); | 
 | 2430 |                   card->hbpool.count++; | 
 | 2431 |                } | 
 | 2432 |             } | 
 | 2433 | 	 } | 
 | 2434 | 	 else | 
 | 2435 |          if (--card->hbpool.count < card->hbnr.min) | 
 | 2436 |          { | 
 | 2437 |             struct sk_buff *new_hb; | 
 | 2438 |             if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) | 
 | 2439 |             { | 
 | 2440 |                skb_queue_tail(&card->hbpool.queue, new_hb); | 
 | 2441 |                card->hbpool.count++; | 
 | 2442 |             } | 
 | 2443 |             if (card->hbpool.count < card->hbnr.min) | 
 | 2444 | 	    { | 
 | 2445 |                if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) | 
 | 2446 |                { | 
 | 2447 |                   skb_queue_tail(&card->hbpool.queue, new_hb); | 
 | 2448 |                   card->hbpool.count++; | 
 | 2449 |                } | 
 | 2450 |             } | 
 | 2451 |          } | 
 | 2452 |  | 
 | 2453 |          iov = (struct iovec *) iovb->data; | 
 | 2454 |  | 
 | 2455 |          if (!atm_charge(vcc, hb->truesize)) | 
 | 2456 | 	 { | 
 | 2457 |             recycle_iovec_rx_bufs(card, iov, NS_SKB(iovb)->iovcnt); | 
 | 2458 |             if (card->hbpool.count < card->hbnr.max) | 
 | 2459 |             { | 
 | 2460 |                skb_queue_tail(&card->hbpool.queue, hb); | 
 | 2461 |                card->hbpool.count++; | 
 | 2462 |             } | 
 | 2463 | 	    else | 
 | 2464 | 	       dev_kfree_skb_any(hb); | 
 | 2465 | 	    atomic_inc(&vcc->stats->rx_drop); | 
 | 2466 |          } | 
 | 2467 |          else | 
 | 2468 | 	 { | 
 | 2469 |             /* Copy the small buffer to the huge buffer */ | 
 | 2470 |             sb = (struct sk_buff *) iov->iov_base; | 
 | 2471 |             memcpy(hb->data, sb->data, iov->iov_len); | 
 | 2472 |             skb_put(hb, iov->iov_len); | 
 | 2473 |             remaining = len - iov->iov_len; | 
 | 2474 |             iov++; | 
 | 2475 |             /* Free the small buffer */ | 
 | 2476 |             push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), | 
 | 2477 |                         0, 0); | 
 | 2478 |  | 
 | 2479 |             /* Copy all large buffers to the huge buffer and free them */ | 
 | 2480 |             for (j = 1; j < NS_SKB(iovb)->iovcnt; j++) | 
 | 2481 |             { | 
 | 2482 |                lb = (struct sk_buff *) iov->iov_base; | 
 | 2483 |                tocopy = min_t(int, remaining, iov->iov_len); | 
 | 2484 |                memcpy(hb->tail, lb->data, tocopy); | 
 | 2485 |                skb_put(hb, tocopy); | 
 | 2486 |                iov++; | 
 | 2487 |                remaining -= tocopy; | 
 | 2488 |                push_rxbufs(card, BUF_LG, (u32) lb, | 
 | 2489 |                            (u32) virt_to_bus(lb->data), 0, 0); | 
 | 2490 |             } | 
 | 2491 | #ifdef EXTRA_DEBUG | 
 | 2492 |             if (remaining != 0 || hb->len != len) | 
 | 2493 |                printk("nicstar%d: Huge buffer len mismatch.\n", card->index); | 
 | 2494 | #endif /* EXTRA_DEBUG */ | 
 | 2495 |             ATM_SKB(hb)->vcc = vcc; | 
 | 2496 | #ifdef NS_USE_DESTRUCTORS | 
 | 2497 |             hb->destructor = ns_hb_destructor; | 
 | 2498 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 2499 |             do_gettimeofday(&hb->stamp); | 
 | 2500 |             vcc->push(vcc, hb); | 
 | 2501 |             atomic_inc(&vcc->stats->rx); | 
 | 2502 |          } | 
 | 2503 |       } | 
 | 2504 |  | 
 | 2505 |       vc->rx_iov = NULL; | 
 | 2506 |       recycle_iov_buf(card, iovb); | 
 | 2507 |    } | 
 | 2508 |  | 
 | 2509 | } | 
 | 2510 |  | 
 | 2511 |  | 
 | 2512 |  | 
 | 2513 | #ifdef NS_USE_DESTRUCTORS | 
 | 2514 |  | 
 | 2515 | static void ns_sb_destructor(struct sk_buff *sb) | 
 | 2516 | { | 
 | 2517 |    ns_dev *card; | 
 | 2518 |    u32 stat; | 
 | 2519 |  | 
 | 2520 |    card = (ns_dev *) ATM_SKB(sb)->vcc->dev->dev_data; | 
 | 2521 |    stat = readl(card->membase + STAT); | 
 | 2522 |    card->sbfqc = ns_stat_sfbqc_get(stat);    | 
 | 2523 |    card->lbfqc = ns_stat_lfbqc_get(stat); | 
 | 2524 |  | 
 | 2525 |    do | 
 | 2526 |    { | 
 | 2527 |       sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); | 
 | 2528 |       if (sb == NULL) | 
 | 2529 |          break; | 
 | 2530 |       skb_queue_tail(&card->sbpool.queue, sb); | 
 | 2531 |       skb_reserve(sb, NS_AAL0_HEADER); | 
 | 2532 |       push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | 
 | 2533 |    } while (card->sbfqc < card->sbnr.min); | 
 | 2534 | } | 
 | 2535 |  | 
 | 2536 |  | 
 | 2537 |  | 
 | 2538 | static void ns_lb_destructor(struct sk_buff *lb) | 
 | 2539 | { | 
 | 2540 |    ns_dev *card; | 
 | 2541 |    u32 stat; | 
 | 2542 |  | 
 | 2543 |    card = (ns_dev *) ATM_SKB(lb)->vcc->dev->dev_data; | 
 | 2544 |    stat = readl(card->membase + STAT); | 
 | 2545 |    card->sbfqc = ns_stat_sfbqc_get(stat);    | 
 | 2546 |    card->lbfqc = ns_stat_lfbqc_get(stat); | 
 | 2547 |  | 
 | 2548 |    do | 
 | 2549 |    { | 
 | 2550 |       lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); | 
 | 2551 |       if (lb == NULL) | 
 | 2552 |          break; | 
 | 2553 |       skb_queue_tail(&card->lbpool.queue, lb); | 
 | 2554 |       skb_reserve(lb, NS_SMBUFSIZE); | 
 | 2555 |       push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | 
 | 2556 |    } while (card->lbfqc < card->lbnr.min); | 
 | 2557 | } | 
 | 2558 |  | 
 | 2559 |  | 
 | 2560 |  | 
 | 2561 | static void ns_hb_destructor(struct sk_buff *hb) | 
 | 2562 | { | 
 | 2563 |    ns_dev *card; | 
 | 2564 |  | 
 | 2565 |    card = (ns_dev *) ATM_SKB(hb)->vcc->dev->dev_data; | 
 | 2566 |  | 
 | 2567 |    while (card->hbpool.count < card->hbnr.init) | 
 | 2568 |    { | 
 | 2569 |       hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); | 
 | 2570 |       if (hb == NULL) | 
 | 2571 |          break; | 
 | 2572 |       skb_queue_tail(&card->hbpool.queue, hb); | 
 | 2573 |       card->hbpool.count++; | 
 | 2574 |    } | 
 | 2575 | } | 
 | 2576 |  | 
 | 2577 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 2578 |  | 
 | 2579 |  | 
 | 2580 |  | 
 | 2581 | static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb) | 
 | 2582 | { | 
 | 2583 |    if (skb->list == &card->sbpool.queue) | 
 | 2584 |       push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0); | 
 | 2585 |    else if (skb->list == &card->lbpool.queue) | 
 | 2586 |       push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0); | 
 | 2587 |    else | 
 | 2588 |    { | 
 | 2589 |       printk("nicstar%d: What kind of rx buffer is this?\n", card->index); | 
 | 2590 |       dev_kfree_skb_any(skb); | 
 | 2591 |    } | 
 | 2592 | } | 
 | 2593 |  | 
 | 2594 |  | 
 | 2595 |  | 
 | 2596 | static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count) | 
 | 2597 | { | 
 | 2598 |    struct sk_buff *skb; | 
 | 2599 |  | 
 | 2600 |    for (; count > 0; count--) | 
 | 2601 |    { | 
 | 2602 |       skb = (struct sk_buff *) (iov++)->iov_base; | 
 | 2603 |       if (skb->list == &card->sbpool.queue) | 
 | 2604 |          push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), | 
 | 2605 | 	             0, 0); | 
 | 2606 |       else if (skb->list == &card->lbpool.queue) | 
 | 2607 |          push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data), | 
 | 2608 | 	             0, 0); | 
 | 2609 |       else | 
 | 2610 |       { | 
 | 2611 |          printk("nicstar%d: What kind of rx buffer is this?\n", card->index); | 
 | 2612 |          dev_kfree_skb_any(skb); | 
 | 2613 |       } | 
 | 2614 |    } | 
 | 2615 | } | 
 | 2616 |  | 
 | 2617 |  | 
 | 2618 |  | 
 | 2619 | static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb) | 
 | 2620 | { | 
 | 2621 |    if (card->iovpool.count < card->iovnr.max) | 
 | 2622 |    { | 
 | 2623 |       skb_queue_tail(&card->iovpool.queue, iovb); | 
 | 2624 |       card->iovpool.count++; | 
 | 2625 |    } | 
 | 2626 |    else | 
 | 2627 |       dev_kfree_skb_any(iovb); | 
 | 2628 | } | 
 | 2629 |  | 
 | 2630 |  | 
 | 2631 |  | 
 | 2632 | static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb) | 
 | 2633 | { | 
 | 2634 |    skb_unlink(sb); | 
 | 2635 | #ifdef NS_USE_DESTRUCTORS | 
 | 2636 |    if (card->sbfqc < card->sbnr.min) | 
 | 2637 | #else | 
 | 2638 |    if (card->sbfqc < card->sbnr.init) | 
 | 2639 |    { | 
 | 2640 |       struct sk_buff *new_sb; | 
 | 2641 |       if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) | 
 | 2642 |       { | 
 | 2643 |          skb_queue_tail(&card->sbpool.queue, new_sb); | 
 | 2644 |          skb_reserve(new_sb, NS_AAL0_HEADER); | 
 | 2645 |          push_rxbufs(card, BUF_SM, (u32) new_sb, | 
 | 2646 |                      (u32) virt_to_bus(new_sb->data), 0, 0); | 
 | 2647 |       } | 
 | 2648 |    } | 
 | 2649 |    if (card->sbfqc < card->sbnr.init) | 
 | 2650 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 2651 |    { | 
 | 2652 |       struct sk_buff *new_sb; | 
 | 2653 |       if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) | 
 | 2654 |       { | 
 | 2655 |          skb_queue_tail(&card->sbpool.queue, new_sb); | 
 | 2656 |          skb_reserve(new_sb, NS_AAL0_HEADER); | 
 | 2657 |          push_rxbufs(card, BUF_SM, (u32) new_sb, | 
 | 2658 |                      (u32) virt_to_bus(new_sb->data), 0, 0); | 
 | 2659 |       } | 
 | 2660 |    } | 
 | 2661 | } | 
 | 2662 |  | 
 | 2663 |  | 
 | 2664 |  | 
 | 2665 | static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb) | 
 | 2666 | { | 
 | 2667 |    skb_unlink(lb); | 
 | 2668 | #ifdef NS_USE_DESTRUCTORS | 
 | 2669 |    if (card->lbfqc < card->lbnr.min) | 
 | 2670 | #else | 
 | 2671 |    if (card->lbfqc < card->lbnr.init) | 
 | 2672 |    { | 
 | 2673 |       struct sk_buff *new_lb; | 
 | 2674 |       if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) | 
 | 2675 |       { | 
 | 2676 |          skb_queue_tail(&card->lbpool.queue, new_lb); | 
 | 2677 |          skb_reserve(new_lb, NS_SMBUFSIZE); | 
 | 2678 |          push_rxbufs(card, BUF_LG, (u32) new_lb, | 
 | 2679 |                      (u32) virt_to_bus(new_lb->data), 0, 0); | 
 | 2680 |       } | 
 | 2681 |    } | 
 | 2682 |    if (card->lbfqc < card->lbnr.init) | 
 | 2683 | #endif /* NS_USE_DESTRUCTORS */ | 
 | 2684 |    { | 
 | 2685 |       struct sk_buff *new_lb; | 
 | 2686 |       if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) | 
 | 2687 |       { | 
 | 2688 |          skb_queue_tail(&card->lbpool.queue, new_lb); | 
 | 2689 |          skb_reserve(new_lb, NS_SMBUFSIZE); | 
 | 2690 |          push_rxbufs(card, BUF_LG, (u32) new_lb, | 
 | 2691 |                      (u32) virt_to_bus(new_lb->data), 0, 0); | 
 | 2692 |       } | 
 | 2693 |    } | 
 | 2694 | } | 
 | 2695 |  | 
 | 2696 |  | 
 | 2697 |  | 
 | 2698 | static int ns_proc_read(struct atm_dev *dev, loff_t *pos, char *page) | 
 | 2699 | { | 
 | 2700 |    u32 stat; | 
 | 2701 |    ns_dev *card; | 
 | 2702 |    int left; | 
 | 2703 |  | 
 | 2704 |    left = (int) *pos; | 
 | 2705 |    card = (ns_dev *) dev->dev_data; | 
 | 2706 |    stat = readl(card->membase + STAT); | 
 | 2707 |    if (!left--) | 
 | 2708 |       return sprintf(page, "Pool   count    min   init    max \n"); | 
 | 2709 |    if (!left--) | 
 | 2710 |       return sprintf(page, "Small  %5d  %5d  %5d  %5d \n", | 
 | 2711 |                      ns_stat_sfbqc_get(stat), card->sbnr.min, card->sbnr.init, | 
 | 2712 | 		     card->sbnr.max); | 
 | 2713 |    if (!left--) | 
 | 2714 |       return sprintf(page, "Large  %5d  %5d  %5d  %5d \n", | 
 | 2715 |                      ns_stat_lfbqc_get(stat), card->lbnr.min, card->lbnr.init, | 
 | 2716 | 		     card->lbnr.max); | 
 | 2717 |    if (!left--) | 
 | 2718 |       return sprintf(page, "Huge   %5d  %5d  %5d  %5d \n", card->hbpool.count, | 
 | 2719 |                      card->hbnr.min, card->hbnr.init, card->hbnr.max); | 
 | 2720 |    if (!left--) | 
 | 2721 |       return sprintf(page, "Iovec  %5d  %5d  %5d  %5d \n", card->iovpool.count, | 
 | 2722 |                      card->iovnr.min, card->iovnr.init, card->iovnr.max); | 
 | 2723 |    if (!left--) | 
 | 2724 |    { | 
 | 2725 |       int retval; | 
 | 2726 |       retval = sprintf(page, "Interrupt counter: %u \n", card->intcnt); | 
 | 2727 |       card->intcnt = 0; | 
 | 2728 |       return retval; | 
 | 2729 |    } | 
 | 2730 | #if 0 | 
 | 2731 |    /* Dump 25.6 Mbps PHY registers */ | 
 | 2732 |    /* Now there's a 25.6 Mbps PHY driver this code isn't needed. I left it | 
 | 2733 |       here just in case it's needed for debugging. */ | 
 | 2734 |    if (card->max_pcr == ATM_25_PCR && !left--) | 
 | 2735 |    { | 
 | 2736 |       u32 phy_regs[4]; | 
 | 2737 |       u32 i; | 
 | 2738 |  | 
 | 2739 |       for (i = 0; i < 4; i++) | 
 | 2740 |       { | 
 | 2741 |          while (CMD_BUSY(card)); | 
 | 2742 |          writel(NS_CMD_READ_UTILITY | 0x00000200 | i, card->membase + CMD); | 
 | 2743 |          while (CMD_BUSY(card)); | 
 | 2744 |          phy_regs[i] = readl(card->membase + DR0) & 0x000000FF; | 
 | 2745 |       } | 
 | 2746 |  | 
 | 2747 |       return sprintf(page, "PHY regs: 0x%02X 0x%02X 0x%02X 0x%02X \n", | 
 | 2748 |                      phy_regs[0], phy_regs[1], phy_regs[2], phy_regs[3]); | 
 | 2749 |    } | 
 | 2750 | #endif /* 0 - Dump 25.6 Mbps PHY registers */ | 
 | 2751 | #if 0 | 
 | 2752 |    /* Dump TST */ | 
 | 2753 |    if (left-- < NS_TST_NUM_ENTRIES) | 
 | 2754 |    { | 
 | 2755 |       if (card->tste2vc[left + 1] == NULL) | 
 | 2756 |          return sprintf(page, "%5d - VBR/UBR \n", left + 1); | 
 | 2757 |       else | 
 | 2758 |          return sprintf(page, "%5d - %d %d \n", left + 1, | 
 | 2759 |                         card->tste2vc[left + 1]->tx_vcc->vpi, | 
 | 2760 |                         card->tste2vc[left + 1]->tx_vcc->vci); | 
 | 2761 |    } | 
 | 2762 | #endif /* 0 */ | 
 | 2763 |    return 0; | 
 | 2764 | } | 
 | 2765 |  | 
 | 2766 |  | 
 | 2767 |  | 
 | 2768 | static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) | 
 | 2769 | { | 
 | 2770 |    ns_dev *card; | 
 | 2771 |    pool_levels pl; | 
 | 2772 |    int btype; | 
 | 2773 |    unsigned long flags; | 
 | 2774 |  | 
 | 2775 |    card = dev->dev_data; | 
 | 2776 |    switch (cmd) | 
 | 2777 |    { | 
 | 2778 |       case NS_GETPSTAT: | 
 | 2779 |          if (get_user(pl.buftype, &((pool_levels __user *) arg)->buftype)) | 
 | 2780 | 	    return -EFAULT; | 
 | 2781 |          switch (pl.buftype) | 
 | 2782 | 	 { | 
 | 2783 | 	    case NS_BUFTYPE_SMALL: | 
 | 2784 | 	       pl.count = ns_stat_sfbqc_get(readl(card->membase + STAT)); | 
 | 2785 | 	       pl.level.min = card->sbnr.min; | 
 | 2786 | 	       pl.level.init = card->sbnr.init; | 
 | 2787 | 	       pl.level.max = card->sbnr.max; | 
 | 2788 | 	       break; | 
 | 2789 |  | 
 | 2790 | 	    case NS_BUFTYPE_LARGE: | 
 | 2791 | 	       pl.count = ns_stat_lfbqc_get(readl(card->membase + STAT)); | 
 | 2792 | 	       pl.level.min = card->lbnr.min; | 
 | 2793 | 	       pl.level.init = card->lbnr.init; | 
 | 2794 | 	       pl.level.max = card->lbnr.max; | 
 | 2795 | 	       break; | 
 | 2796 |  | 
 | 2797 | 	    case NS_BUFTYPE_HUGE: | 
 | 2798 | 	       pl.count = card->hbpool.count; | 
 | 2799 | 	       pl.level.min = card->hbnr.min; | 
 | 2800 | 	       pl.level.init = card->hbnr.init; | 
 | 2801 | 	       pl.level.max = card->hbnr.max; | 
 | 2802 | 	       break; | 
 | 2803 |  | 
 | 2804 | 	    case NS_BUFTYPE_IOVEC: | 
 | 2805 | 	       pl.count = card->iovpool.count; | 
 | 2806 | 	       pl.level.min = card->iovnr.min; | 
 | 2807 | 	       pl.level.init = card->iovnr.init; | 
 | 2808 | 	       pl.level.max = card->iovnr.max; | 
 | 2809 | 	       break; | 
 | 2810 |  | 
 | 2811 |             default: | 
 | 2812 | 	       return -ENOIOCTLCMD; | 
 | 2813 |  | 
 | 2814 | 	 } | 
 | 2815 |          if (!copy_to_user((pool_levels __user *) arg, &pl, sizeof(pl))) | 
 | 2816 | 	    return (sizeof(pl)); | 
 | 2817 | 	 else | 
 | 2818 | 	    return -EFAULT; | 
 | 2819 |  | 
 | 2820 |       case NS_SETBUFLEV: | 
 | 2821 |          if (!capable(CAP_NET_ADMIN)) | 
 | 2822 | 	    return -EPERM; | 
 | 2823 |          if (copy_from_user(&pl, (pool_levels __user *) arg, sizeof(pl))) | 
 | 2824 | 	    return -EFAULT; | 
 | 2825 | 	 if (pl.level.min >= pl.level.init || pl.level.init >= pl.level.max) | 
 | 2826 | 	    return -EINVAL; | 
 | 2827 | 	 if (pl.level.min == 0) | 
 | 2828 | 	    return -EINVAL; | 
 | 2829 |          switch (pl.buftype) | 
 | 2830 | 	 { | 
 | 2831 | 	    case NS_BUFTYPE_SMALL: | 
 | 2832 |                if (pl.level.max > TOP_SB) | 
 | 2833 | 	          return -EINVAL; | 
 | 2834 | 	       card->sbnr.min = pl.level.min; | 
 | 2835 | 	       card->sbnr.init = pl.level.init; | 
 | 2836 | 	       card->sbnr.max = pl.level.max; | 
 | 2837 | 	       break; | 
 | 2838 |  | 
 | 2839 | 	    case NS_BUFTYPE_LARGE: | 
 | 2840 |                if (pl.level.max > TOP_LB) | 
 | 2841 | 	          return -EINVAL; | 
 | 2842 | 	       card->lbnr.min = pl.level.min; | 
 | 2843 | 	       card->lbnr.init = pl.level.init; | 
 | 2844 | 	       card->lbnr.max = pl.level.max; | 
 | 2845 | 	       break; | 
 | 2846 |  | 
 | 2847 | 	    case NS_BUFTYPE_HUGE: | 
 | 2848 |                if (pl.level.max > TOP_HB) | 
 | 2849 | 	          return -EINVAL; | 
 | 2850 | 	       card->hbnr.min = pl.level.min; | 
 | 2851 | 	       card->hbnr.init = pl.level.init; | 
 | 2852 | 	       card->hbnr.max = pl.level.max; | 
 | 2853 | 	       break; | 
 | 2854 |  | 
 | 2855 | 	    case NS_BUFTYPE_IOVEC: | 
 | 2856 |                if (pl.level.max > TOP_IOVB) | 
 | 2857 | 	          return -EINVAL; | 
 | 2858 | 	       card->iovnr.min = pl.level.min; | 
 | 2859 | 	       card->iovnr.init = pl.level.init; | 
 | 2860 | 	       card->iovnr.max = pl.level.max; | 
 | 2861 | 	       break; | 
 | 2862 |  | 
 | 2863 |             default: | 
 | 2864 | 	       return -EINVAL; | 
 | 2865 |  | 
 | 2866 |          }	  | 
 | 2867 |          return 0; | 
 | 2868 |  | 
 | 2869 |       case NS_ADJBUFLEV: | 
 | 2870 |          if (!capable(CAP_NET_ADMIN)) | 
 | 2871 | 	    return -EPERM; | 
 | 2872 |          btype = (int) arg;	/* an int is the same size as a pointer */ | 
 | 2873 |          switch (btype) | 
 | 2874 | 	 { | 
 | 2875 | 	    case NS_BUFTYPE_SMALL: | 
 | 2876 | 	       while (card->sbfqc < card->sbnr.init) | 
 | 2877 | 	       { | 
 | 2878 |                   struct sk_buff *sb; | 
 | 2879 |  | 
 | 2880 |                   sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); | 
 | 2881 |                   if (sb == NULL) | 
 | 2882 |                      return -ENOMEM; | 
 | 2883 |                   skb_queue_tail(&card->sbpool.queue, sb); | 
 | 2884 |                   skb_reserve(sb, NS_AAL0_HEADER); | 
 | 2885 |                   push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | 
 | 2886 | 	       } | 
 | 2887 | 	       break; | 
 | 2888 |  | 
 | 2889 |             case NS_BUFTYPE_LARGE: | 
 | 2890 | 	       while (card->lbfqc < card->lbnr.init) | 
 | 2891 | 	       { | 
 | 2892 |                   struct sk_buff *lb; | 
 | 2893 |  | 
 | 2894 |                   lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); | 
 | 2895 |                   if (lb == NULL) | 
 | 2896 |                      return -ENOMEM; | 
 | 2897 |                   skb_queue_tail(&card->lbpool.queue, lb); | 
 | 2898 |                   skb_reserve(lb, NS_SMBUFSIZE); | 
 | 2899 |                   push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | 
 | 2900 | 	       } | 
 | 2901 | 	       break; | 
 | 2902 |  | 
 | 2903 |             case NS_BUFTYPE_HUGE: | 
 | 2904 |                while (card->hbpool.count > card->hbnr.init) | 
 | 2905 | 	       { | 
 | 2906 |                   struct sk_buff *hb; | 
 | 2907 |  | 
 | 2908 |                   ns_grab_int_lock(card, flags); | 
 | 2909 | 		  hb = skb_dequeue(&card->hbpool.queue); | 
 | 2910 | 		  card->hbpool.count--; | 
 | 2911 |                   spin_unlock_irqrestore(&card->int_lock, flags); | 
 | 2912 |                   if (hb == NULL) | 
 | 2913 | 		     printk("nicstar%d: huge buffer count inconsistent.\n", | 
 | 2914 | 		            card->index); | 
 | 2915 |                   else | 
 | 2916 | 		     dev_kfree_skb_any(hb); | 
 | 2917 | 		   | 
 | 2918 | 	       } | 
 | 2919 |                while (card->hbpool.count < card->hbnr.init) | 
 | 2920 |                { | 
 | 2921 |                   struct sk_buff *hb; | 
 | 2922 |  | 
 | 2923 |                   hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); | 
 | 2924 |                   if (hb == NULL) | 
 | 2925 |                      return -ENOMEM; | 
 | 2926 |                   ns_grab_int_lock(card, flags); | 
 | 2927 |                   skb_queue_tail(&card->hbpool.queue, hb); | 
 | 2928 |                   card->hbpool.count++; | 
 | 2929 |                   spin_unlock_irqrestore(&card->int_lock, flags); | 
 | 2930 |                } | 
 | 2931 | 	       break; | 
 | 2932 |  | 
 | 2933 |             case NS_BUFTYPE_IOVEC: | 
 | 2934 | 	       while (card->iovpool.count > card->iovnr.init) | 
 | 2935 | 	       { | 
 | 2936 | 	          struct sk_buff *iovb; | 
 | 2937 |  | 
 | 2938 |                   ns_grab_int_lock(card, flags); | 
 | 2939 | 		  iovb = skb_dequeue(&card->iovpool.queue); | 
 | 2940 | 		  card->iovpool.count--; | 
 | 2941 |                   spin_unlock_irqrestore(&card->int_lock, flags); | 
 | 2942 |                   if (iovb == NULL) | 
 | 2943 | 		     printk("nicstar%d: iovec buffer count inconsistent.\n", | 
 | 2944 | 		            card->index); | 
 | 2945 |                   else | 
 | 2946 | 		     dev_kfree_skb_any(iovb); | 
 | 2947 |  | 
 | 2948 | 	       } | 
 | 2949 |                while (card->iovpool.count < card->iovnr.init) | 
 | 2950 | 	       { | 
 | 2951 | 	          struct sk_buff *iovb; | 
 | 2952 |  | 
 | 2953 |                   iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); | 
 | 2954 |                   if (iovb == NULL) | 
 | 2955 |                      return -ENOMEM; | 
 | 2956 |                   ns_grab_int_lock(card, flags); | 
 | 2957 |                   skb_queue_tail(&card->iovpool.queue, iovb); | 
 | 2958 |                   card->iovpool.count++; | 
 | 2959 |                   spin_unlock_irqrestore(&card->int_lock, flags); | 
 | 2960 | 	       } | 
 | 2961 | 	       break; | 
 | 2962 |  | 
 | 2963 |             default: | 
 | 2964 | 	       return -EINVAL; | 
 | 2965 |  | 
 | 2966 | 	 } | 
 | 2967 |          return 0; | 
 | 2968 |  | 
 | 2969 |       default: | 
 | 2970 |          if (dev->phy && dev->phy->ioctl) { | 
 | 2971 |             return dev->phy->ioctl(dev, cmd, arg); | 
 | 2972 |          } | 
 | 2973 |          else { | 
 | 2974 |             printk("nicstar%d: %s == NULL \n", card->index, | 
 | 2975 |                    dev->phy ? "dev->phy->ioctl" : "dev->phy"); | 
 | 2976 |             return -ENOIOCTLCMD; | 
 | 2977 |          } | 
 | 2978 |    } | 
 | 2979 | } | 
 | 2980 |  | 
 | 2981 |  | 
 | 2982 |  | 
 | 2983 | static void which_list(ns_dev *card, struct sk_buff *skb) | 
 | 2984 | { | 
 | 2985 |    printk("It's a %s buffer.\n", skb->list == &card->sbpool.queue ? | 
 | 2986 |           "small" : skb->list == &card->lbpool.queue ? "large" : | 
 | 2987 | 	  skb->list == &card->hbpool.queue ? "huge" : | 
 | 2988 | 	  skb->list == &card->iovpool.queue ? "iovec" : "unknown"); | 
 | 2989 | } | 
 | 2990 |  | 
 | 2991 |  | 
 | 2992 |  | 
 | 2993 | static void ns_poll(unsigned long arg) | 
 | 2994 | { | 
 | 2995 |    int i; | 
 | 2996 |    ns_dev *card; | 
 | 2997 |    unsigned long flags; | 
 | 2998 |    u32 stat_r, stat_w; | 
 | 2999 |  | 
 | 3000 |    PRINTK("nicstar: Entering ns_poll().\n"); | 
 | 3001 |    for (i = 0; i < num_cards; i++) | 
 | 3002 |    { | 
 | 3003 |       card = cards[i]; | 
 | 3004 |       if (spin_is_locked(&card->int_lock)) { | 
 | 3005 |       /* Probably it isn't worth spinning */ | 
 | 3006 |          continue; | 
 | 3007 |       } | 
 | 3008 |       ns_grab_int_lock(card, flags); | 
 | 3009 |  | 
 | 3010 |       stat_w = 0; | 
 | 3011 |       stat_r = readl(card->membase + STAT); | 
 | 3012 |       if (stat_r & NS_STAT_TSIF) | 
 | 3013 |          stat_w |= NS_STAT_TSIF; | 
 | 3014 |       if (stat_r & NS_STAT_EOPDU) | 
 | 3015 |          stat_w |= NS_STAT_EOPDU; | 
 | 3016 |  | 
 | 3017 |       process_tsq(card); | 
 | 3018 |       process_rsq(card); | 
 | 3019 |  | 
 | 3020 |       writel(stat_w, card->membase + STAT); | 
 | 3021 |       spin_unlock_irqrestore(&card->int_lock, flags); | 
 | 3022 |    } | 
 | 3023 |    mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD); | 
 | 3024 |    PRINTK("nicstar: Leaving ns_poll().\n"); | 
 | 3025 | } | 
 | 3026 |  | 
 | 3027 |  | 
 | 3028 |  | 
 | 3029 | static int ns_parse_mac(char *mac, unsigned char *esi) | 
 | 3030 | { | 
 | 3031 |    int i, j; | 
 | 3032 |    short byte1, byte0; | 
 | 3033 |  | 
 | 3034 |    if (mac == NULL || esi == NULL) | 
 | 3035 |       return -1; | 
 | 3036 |    j = 0; | 
 | 3037 |    for (i = 0; i < 6; i++) | 
 | 3038 |    { | 
 | 3039 |       if ((byte1 = ns_h2i(mac[j++])) < 0) | 
 | 3040 |          return -1; | 
 | 3041 |       if ((byte0 = ns_h2i(mac[j++])) < 0) | 
 | 3042 |          return -1; | 
 | 3043 |       esi[i] = (unsigned char) (byte1 * 16 + byte0); | 
 | 3044 |       if (i < 5) | 
 | 3045 |       { | 
 | 3046 |          if (mac[j++] != ':') | 
 | 3047 |             return -1; | 
 | 3048 |       } | 
 | 3049 |    } | 
 | 3050 |    return 0; | 
 | 3051 | } | 
 | 3052 |  | 
 | 3053 |  | 
 | 3054 |  | 
 | 3055 | static short ns_h2i(char c) | 
 | 3056 | { | 
 | 3057 |    if (c >= '0' && c <= '9') | 
 | 3058 |       return (short) (c - '0'); | 
 | 3059 |    if (c >= 'A' && c <= 'F') | 
 | 3060 |       return (short) (c - 'A' + 10); | 
 | 3061 |    if (c >= 'a' && c <= 'f') | 
 | 3062 |       return (short) (c - 'a' + 10); | 
 | 3063 |    return -1; | 
 | 3064 | } | 
 | 3065 |  | 
 | 3066 |  | 
 | 3067 |  | 
 | 3068 | static void ns_phy_put(struct atm_dev *dev, unsigned char value, | 
 | 3069 |                     unsigned long addr) | 
 | 3070 | { | 
 | 3071 |    ns_dev *card; | 
 | 3072 |    unsigned long flags; | 
 | 3073 |  | 
 | 3074 |    card = dev->dev_data; | 
 | 3075 |    ns_grab_res_lock(card, flags); | 
 | 3076 |    while(CMD_BUSY(card)); | 
 | 3077 |    writel((unsigned long) value, card->membase + DR0); | 
 | 3078 |    writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), | 
 | 3079 |           card->membase + CMD); | 
 | 3080 |    spin_unlock_irqrestore(&card->res_lock, flags); | 
 | 3081 | } | 
 | 3082 |  | 
 | 3083 |  | 
 | 3084 |  | 
 | 3085 | static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr) | 
 | 3086 | { | 
 | 3087 |    ns_dev *card; | 
 | 3088 |    unsigned long flags; | 
 | 3089 |    unsigned long data; | 
 | 3090 |  | 
 | 3091 |    card = dev->dev_data; | 
 | 3092 |    ns_grab_res_lock(card, flags); | 
 | 3093 |    while(CMD_BUSY(card)); | 
 | 3094 |    writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF), | 
 | 3095 |           card->membase + CMD); | 
 | 3096 |    while(CMD_BUSY(card)); | 
 | 3097 |    data = readl(card->membase + DR0) & 0x000000FF; | 
 | 3098 |    spin_unlock_irqrestore(&card->res_lock, flags); | 
 | 3099 |    return (unsigned char) data; | 
 | 3100 | } | 
 | 3101 |  | 
 | 3102 |  | 
 | 3103 |  | 
 | 3104 | module_init(nicstar_init); | 
 | 3105 | module_exit(nicstar_cleanup); |