📄 c7000.c
字号:
#define c7000_set_busy(dev) netif_stop_queue(dev) /* Clear the device structure transmission busy flag.*/#define c7000_clear_busy(dev) netif_wake_queue(dev)/* Extract the device structure transmission busy flag.*/#define c7000_check_busy(dev) netif_queue_stopped(dev)/* Set a bit in the device structure transmission busy flag.*/static __inline__ voidc7000_setbit_busy(int nr, struct net_device *dev){ netif_stop_queue(dev); test_and_set_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy); return;}/* Clear a bit in the device structure transmission busy flag.*/static __inline__ voidc7000_clearbit_busy(int nr, struct net_device *dev){ clear_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy); netif_wake_queue(dev); return;}/* Test and set a bit in the device structure transmission busy flag.*/static __inline__ intc7000_ts_busy(int nr, struct net_device *dev){ netif_stop_queue(dev); return test_and_set_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy);}/* Set the C7000 controller in the error state.*/static voidc7000_error(struct c7000_controller *ccp){ int i; struct c7000_unit *cup; struct net_device *dev = ccp->dev; for (i = 0; i < NUNITS; i++) { cup = &ccp->cunits[i]; cup->state = C7000_ERROR; } if (dev != NULL) /* RBH XXX Should we be doing this? */ dev->state &= ~__LINK_STATE_START; CPrintk(0, "c7000: c7000_error: base unit 0x%x is down\n", ccp->base_addr); return;}/* Based on the SENSE ID information, fill in the controller name. Note that this is the SENSE ID information saved by LINUX/390 at boot time.*/static intc7000_check_type(senseid_t *id){ switch (id->cu_type) { case C7000_CU_TYPE: if (id->cu_model == C7000_CU_MODEL) { controller = "C7000 "; return(0); } break; default: break; } return(-1);}/* Check the device information for the controller.*/static intc7000_check_devices(int devno){ int i; s390_dev_info_t temp; /* Get the SENSE ID information for each device. */ for (i = devno; i < (devno + NUNITS); i++) { if (get_dev_info_by_devno(devno, &temp) != 0) return(-1); if (c7000_check_type(&temp.sid_data) == -1) return(-1); } CPrintk(1, "c7000: c7000_check_devices: device type is %s\n", controller); return(0);}/* Issue a halt I/O to device pointed to by cup.*/static intc7000_haltio(struct c7000_unit *cup){ unsigned long parm; __u8 flags = 0x00; unsigned long saveflags; DECLARE_WAITQUEUE(wait, current); int rc; s390irq_spin_lock_irqsave(cup->irq, saveflags); parm = (unsigned long)cup; if ((rc = halt_IO(cup->irq, parm, flags)) != 0) { s390irq_spin_unlock_irqrestore(cup->irq, saveflags); return(rc); } /* Wait for the halt I/O to finish. */ add_wait_queue(&cup->wait, &wait); current->state = TASK_UNINTERRUPTIBLE; s390irq_spin_unlock_irqrestore(cup->irq, saveflags); schedule(); remove_wait_queue(&cup->wait, &wait); return(0);}/* Issue a start I/O to device pointed to by cup.*/static intc7000_doio(struct c7000_unit *cup){ unsigned long parm; __u8 flags = 0x00; unsigned long saveflags; DECLARE_WAITQUEUE(wait, current); int rc; /* Do no further I/O while the device is in the ERROR, STOP or STOPPED state. */ if (cup->state == C7000_ERROR || cup->state == C7000_STOP || cup->state == C7000_STOPPED) return(-1); s390irq_spin_lock_irqsave(cup->irq, saveflags); parm = (unsigned long)cup; if ((rc = do_IO(cup->irq, &cup->ccws[0], parm, 0xff, flags)) != 0) { s390irq_spin_unlock_irqrestore(cup->irq, saveflags); return(rc); } /* Wait for the I/O to complete. */ add_wait_queue(&cup->wait, &wait); current->state = TASK_UNINTERRUPTIBLE; s390irq_spin_unlock_irqrestore(cup->irq, saveflags); schedule(); remove_wait_queue(&cup->wait, &wait); /* Interrupt handling may have marked the device in ERROR. */ if (cup->state == C7000_ERROR) return(-1); return(0);}/* Build a channel program to do a sense id channel program.*/static voidc7000_bld_senseid_chpgm(struct c7000_unit *cup){ ccw1_t *ccwp; ccwp = &cup->ccws[0]; ccwp->cmd_code = C7000_SID_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(&cup->senseid); ccwp->count = SIDL; ccwp++; ccwp->cmd_code = C7000_NOOP_CCW; ccwp->flags = CCW_FLAG_SLI; ccwp->cda = (__u32)NULL; ccwp->count = 1; return;}/* Build a channel program to write a control message.*/static voidc7000_bld_wrtctl_chpgm(struct c7000_unit *cup){ ccw1_t *ccwp; ccwp = &cup->ccws[0]; ccwp->cmd_code = C7000_WRITE_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(&cup->control_blk); ccwp->count = sizeof(struct c7000_control_blk); ccwp++; ccwp->cmd_code = C7000_READFF_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(&cup->readff); ccwp->count = C7000_READFFL; ccwp++; ccwp->cmd_code = C7000_TIC_CCW; ccwp->flags = 0; ccwp->cda = (__u32)virt_to_phys(ccwp + 1); ccwp->count = 0; ccwp++; ccwp->cmd_code = C7000_NOOP_CCW; ccwp->flags = CCW_FLAG_SLI; ccwp->cda = (__u32)NULL; ccwp->count = 1; return;}/* Build a write channel program to write the indicated buffer.*/static voidc7000_bld_wrt_chpgm(struct c7000_unit *cup, struct c7000_buffer *buf){ ccw1_t *ccwp; struct c7000_controller *ccp = cup->cntlp; ccwp = &buf->ccws[0]; ccwp->cmd_code = C7000_WRITE_CCW | (ccp->linkid << 3); ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(buf->data); ccwp->count = buf->len; ccwp++; ccwp->cmd_code = C7000_READFF_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(buf->data + C7000_DATAL + C7000_READHDRL); ccwp->count = C7000_READFFL; ccwp++; ccwp->cmd_code = C7000_TIC_CCW; ccwp->flags = 0; ccwp->cda = (__u32)virt_to_phys(ccwp + 1); ccwp->count = 0; ccwp++; ccwp->cmd_code = C7000_NOOP_CCW; ccwp->flags = (CCW_FLAG_SLI); ccwp->cda = (__u32)NULL; ccwp->count = 1; return;}/* Build a channel program to read a control message.*/static voidc7000_bld_readctl_chpgm(struct c7000_unit *cup){ ccw1_t *ccwp; ccwp = &cup->ccws[0]; ccwp->cmd_code = C7000_READ_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(&cup->control_blk); ccwp->count = sizeof(struct c7000_control_blk); ccwp++; ccwp->cmd_code = C7000_READHDR_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(&cup->readhdr); ccwp->count = C7000_READHDRL; ccwp++; ccwp->cmd_code = C7000_SIGSMOD_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(&cup->sigsmod); ccwp->count = C7000_SIGSMODL; ccwp++; ccwp->cmd_code = C7000_TIC_CCW; ccwp->flags = 0; ccwp->cda = (__u32)virt_to_phys(ccwp + 1); ccwp->count = 0; ccwp++; ccwp->cmd_code = C7000_NOOP_CCW; ccwp->flags = (CCW_FLAG_SLI); ccwp->cda = (__u32)NULL; ccwp->count = 1; return;}/* Build a channel program to read the indicated buffer.*/static voidc7000_bld_read_chpgm(struct c7000_unit *cup, struct c7000_buffer *buf){ ccw1_t *ccwp; ccwp = &buf->ccws[0]; ccwp->cmd_code = C7000_READ_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(buf->data); ccwp->count = C7000_DATAL; ccwp++; ccwp->cmd_code = C7000_READHDR_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(buf->data + C7000_DATAL); ccwp->count = C7000_READHDRL; ccwp++; ccwp->cmd_code = C7000_SIGSMOD_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC); ccwp->cda = (__u32)virt_to_phys(&cup->sigsmod); ccwp->count = C7000_SIGSMODL; ccwp++; ccwp->cmd_code = C7000_TIC_CCW; ccwp->flags = 0; ccwp->cda = (__u32)virt_to_phys(ccwp + 3); ccwp->count = 0; ccwp++; ccwp->cmd_code = C7000_READFF_CCW; ccwp->flags = (CCW_FLAG_SLI | CCW_FLAG_CC | CCW_FLAG_PCI); ccwp->cda = (__u32)virt_to_phys(&cup->readff); ccwp->count = C7000_READFFL; ccwp++; ccwp->cmd_code = C7000_TIC_CCW; ccwp->flags = 0; ccwp->cda = (__u32)virt_to_phys(ccwp + 1); ccwp->count = 0; ccwp++; ccwp->cmd_code = C7000_NOOP_CCW; ccwp->flags = (CCW_FLAG_SLI); ccwp->cda = (__u32)NULL; ccwp->count = 1; return;}/* Allocate buffer structure headers and buffers for all units A return value of 0 means that all allocations worked. A -1 means that an allocation failed. It is expected that the caller will call c7000_free_buffers when -1 is returned.*/static intc7000_alloc_buffers(struct net_device *dev){ int i; int j; char *data; struct c7000_buffer *bufptr; struct c7000_controller *ccp = (struct c7000_controller *) dev->priv; struct c7000_unit *cup; for (i = 0; i < NUNITS; i++) { cup = &ccp->cunits[i]; cup->free = NULL; for (j = 0; j < C7000_MAXBUF; j++) { bufptr = kmalloc(sizeof(struct c7000_buffer), GFP_KERNEL); data = kmalloc(C7000_BUFSIZE, GFP_KERNEL); if (bufptr == NULL || data == NULL) { if (bufptr) kfree(bufptr); if (data) kfree(data); return(-1); } /* Place filled in buffer header on free anchor. */ bufptr->next = cup->free; bufptr->data = data; bufptr->len = 0; cup->free = bufptr; if (data == NULL) return(-1); memset(data, '\0', C7000_BUFSIZE); } } CPrintk(1, "c7000: c7000_alloc_buffers: allocated buffers for base unit 0x%lx\n", dev->base_addr); return(0);}/* Free buffers on a chain.*/static voidc7000_free_chain(struct c7000_buffer *buf){ char *data; struct c7000_buffer *bufptr = buf; struct c7000_buffer *tmp; while (bufptr != NULL) { data = bufptr->data; if (data != NULL) kfree(data); tmp = bufptr; bufptr = bufptr->next; kfree(tmp); } return;}/* Free buffers on all possible chains for all units.*/static voidc7000_free_buffers(struct net_device *dev){ int i; struct c7000_controller *ccp = (struct c7000_controller *) dev->priv; struct c7000_unit *cup; for (i = 0; i < NUNITS; i++) { cup = &ccp->cunits[i]; c7000_free_chain(cup->free); cup->free = NULL; c7000_free_chain(cup->proc_head); cup->proc_head = cup->proc_tail = NULL; c7000_free_chain(cup->bh_head); cup->bh_head = cup->bh_tail = NULL; } CPrintk(1, "c7000: c7000_free_buffers: freed buffers for base unit 0x%lx\n", dev->base_addr); return;}/* Obtain a free buffer. Return a pointer to the c7000_buffer structure OR NULL.*/struct c7000_buffer *c7000_get_buffer(struct c7000_unit *cup) { struct c7000_buffer *buf; buf = cup->free; if (buf == NULL) return(NULL); cup->free = buf->next; buf->next = NULL; return(buf);}/* Release a buffer to the free list.*/voidc7000_release_buffer(struct c7000_unit *cup, struct c7000_buffer *buf){ struct c7000_buffer *tmp; tmp = cup->free; cup->free = buf; buf->next = tmp; return;}/* Queue a buffer on the end of the processing (proc) chain.*/voidc7000_queue_buffer(struct c7000_unit *cup, struct c7000_buffer *buf){ buf->next = NULL; if (cup->proc_head == NULL) { cup->proc_head = cup->proc_tail = buf; return; } cup->proc_tail->next = buf; cup->proc_tail = buf; return;}/* Dequeue a buffer from the start of the processing (proc) chain.*/struct c7000_buffer *c7000_dequeue_buffer(struct c7000_unit *cup){ struct c7000_buffer *buf = cup->proc_head; if (buf == NULL) return(NULL); cup->proc_head = buf->next; if (cup->proc_head == NULL) cup->proc_tail = NULL; buf->next = NULL; return(buf);}/* Queue a buffer on the end of the bh routine chain.*/voidc7000_queue_bh_buffer(struct c7000_unit *cup, struct c7000_buffer *buf){ buf->next = NULL; if (cup->bh_head == NULL) { cup->bh_head = cup->bh_tail = buf; return; } cup->bh_tail->next = buf; cup->bh_tail = buf; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -