static int receive_pcb(struct net_device *dev, pcb_struct * pcb) { int i, j; int total_length; int stat; unsigned long timeout; unsigned long flags; elp_device *adapter = dev->priv; set_hsf(dev, 0); /* get the command code */ timeout = jiffies + 2*HZ/100; while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); return FALSE; } pcb->command = inb_command(dev->base_addr); /* read the data length */ timeout = jiffies + 3*HZ/100; while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); printk(KERN_INFO "%s: status %02x\n", dev->name, stat); return FALSE; } pcb->length = inb_command(dev->base_addr); if (pcb->length > MAX_PCB_DATA) { INVALID_PCB_MSG(pcb->length); adapter_reset(dev); return FALSE; } /* read the data */ spin_lock_irqsave(&adapter->lock, flags); i = 0; do { j = 0; while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && j++ < 20000); pcb->data.raw[i++] = inb_command(dev->base_addr); if (i > MAX_PCB_DATA) INVALID_PCB_MSG(i); } while ((stat & ASF_PCB_MASK) != ASF_PCB_END && j < 20000); spin_unlock_irqrestore(&adapter->lock, flags); if (j >= 20000) { TIMEOUT_MSG(__LINE__); return FALSE; } /* woops, the last "data" byte was really the length! */ total_length = pcb->data.raw[--i]; /* safety check total length vs data length */ if (total_length != (pcb->length + 2)) { if (elp_debug >= 2) printk(KERN_WARNING "%s: mangled PCB received\n", dev->name); set_hsf(dev, HSF_PCB_NAK); return FALSE; } if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) { if (test_and_set_bit(0, (void *) &adapter->busy)) { if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) { set_hsf(dev, HSF_PCB_NAK); printk(KERN_WARNING "%s: PCB rejected, transfer in progress and backlog full\n", dev->name); pcb->command = 0; return TRUE; } else { pcb->command = 0xff; } } } set_hsf(dev, HSF_PCB_ACK); return TRUE; }
static bool receive_pcb(struct net_device *dev, pcb_struct * pcb) { int i, j; int total_length; int stat; unsigned long timeout; unsigned long flags; elp_device *adapter = netdev_priv(dev); set_hsf(dev, 0); timeout = jiffies + 2*HZ/100; while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); return false; } pcb->command = inb_command(dev->base_addr); timeout = jiffies + 3*HZ/100; while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) { TIMEOUT_MSG(__LINE__); pr_info("%s: status %02x\n", dev->name, stat); return false; } pcb->length = inb_command(dev->base_addr); if (pcb->length > MAX_PCB_DATA) { INVALID_PCB_MSG(pcb->length); adapter_reset(dev); return false; } spin_lock_irqsave(&adapter->lock, flags); for (i = 0; i < MAX_PCB_DATA; i++) { for (j = 0; j < 20000; j++) { stat = get_status(dev->base_addr); if (stat & ACRF) break; } pcb->data.raw[i] = inb_command(dev->base_addr); if ((stat & ASF_PCB_MASK) == ASF_PCB_END || j >= 20000) break; } spin_unlock_irqrestore(&adapter->lock, flags); if (i >= MAX_PCB_DATA) { INVALID_PCB_MSG(i); return false; } if (j >= 20000) { TIMEOUT_MSG(__LINE__); return false; } total_length = pcb->data.raw[i]; if (total_length != (pcb->length + 2)) { if (elp_debug >= 2) pr_warning("%s: mangled PCB received\n", dev->name); set_hsf(dev, HSF_PCB_NAK); return false; } if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) { if (test_and_set_bit(0, (void *) &adapter->busy)) { if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) { set_hsf(dev, HSF_PCB_NAK); pr_warning("%s: PCB rejected, transfer in progress and backlog full\n", dev->name); pcb->command = 0; return true; } else { pcb->command = 0xff; } } } set_hsf(dev, HSF_PCB_ACK); return true; }