irqreturn_t iop_ism_irq(int irq, void *dev_id) { uint iop_num = (uint) dev_id; volatile struct mac_iop *iop = iop_base[iop_num]; int i,state; #ifdef DEBUG_IOP printk("iop_ism_irq: status = %02X\n", (uint) iop->status_ctrl); #endif /* INT0 indicates a state change on an outgoing message channel */ if (iop->status_ctrl & IOP_INT0) { iop->status_ctrl = IOP_INT0 | IOP_RUN | IOP_AUTOINC; #ifdef DEBUG_IOP printk("iop_ism_irq: new status = %02X, send states", (uint) iop->status_ctrl); #endif for (i = 0 ; i < NUM_IOP_CHAN ; i++) { state = iop_readb(iop, IOP_ADDR_SEND_STATE + i); #ifdef DEBUG_IOP printk(" %02X", state); #endif if (state == IOP_MSG_COMPLETE) { iop_handle_send(iop_num, i); } } #ifdef DEBUG_IOP printk("\n"); #endif } if (iop->status_ctrl & IOP_INT1) { /* INT1 for incoming msgs */ iop->status_ctrl = IOP_INT1 | IOP_RUN | IOP_AUTOINC; #ifdef DEBUG_IOP printk("iop_ism_irq: new status = %02X, recv states", (uint) iop->status_ctrl); #endif for (i = 0 ; i < NUM_IOP_CHAN ; i++) { state = iop_readb(iop, IOP_ADDR_RECV_STATE + i); #ifdef DEBUG_IOP printk(" %02X", state); #endif if (state == IOP_MSG_NEW) { iop_handle_recv(iop_num, i); } } #ifdef DEBUG_IOP printk("\n"); #endif } return IRQ_HANDLED; }
int iop_send_message(uint iop_num, uint chan, void *privdata, uint msg_len, __u8 *msg_data, void (*handler)(struct iop_msg *)) { struct iop_msg *msg, *q; if ((iop_num >= NUM_IOPS) || !iop_base[iop_num]) return -EINVAL; if (chan >= NUM_IOP_CHAN) return -EINVAL; if (msg_len > IOP_MSG_LEN) return -EINVAL; msg = iop_alloc_msg(); if (!msg) return -ENOMEM; msg->next = NULL; msg->status = IOP_MSGSTATUS_WAITING; msg->iop_num = iop_num; msg->channel = chan; msg->caller_priv = privdata; memcpy(msg->message, msg_data, msg_len); msg->handler = handler; if (!(q = iop_send_queue[iop_num][chan])) { iop_send_queue[iop_num][chan] = msg; } else { while (q->next) q = q->next; q->next = msg; } if (iop_readb(iop_base[iop_num], IOP_ADDR_SEND_STATE + chan) == IOP_MSG_IDLE) { iop_do_send(msg); } return 0; }
static void iop_handle_send(uint iop_num, uint chan) { volatile struct mac_iop *iop = iop_base[iop_num]; struct iop_msg *msg,*msg2; int i,offset; #ifdef DEBUG_IOP printk("iop_handle_send: iop %d channel %d\n", iop_num, chan); #endif iop_writeb(iop, IOP_ADDR_SEND_STATE + chan, IOP_MSG_IDLE); if (!(msg = iop_send_queue[iop_num][chan])) return; msg->status = IOP_MSGSTATUS_COMPLETE; offset = IOP_ADDR_SEND_MSG + (chan * IOP_MSG_LEN); for (i = 0 ; i < IOP_MSG_LEN ; i++, offset++) { msg->reply[i] = iop_readb(iop, offset); } if (msg->handler) (*msg->handler)(msg); msg2 = msg; msg = msg->next; iop_free_msg(msg2); iop_send_queue[iop_num][chan] = msg; if (msg) iop_do_send(msg); }
static int iop_alive(volatile struct mac_iop *iop) { int retval; retval = (iop_readb(iop, IOP_ADDR_ALIVE) == 0xFF); iop_writeb(iop, IOP_ADDR_ALIVE, 0); return retval; }
int iop_dump_one_iop(char *buf, int iop_num, char *iop_name) { int i,len = 0; volatile struct mac_iop *iop = iop_base[iop_num]; len += sprintf(buf+len, "%s IOP channel states:\n\n", iop_name); len += sprintf(buf+len, "## send_state recv_state device\n"); len += sprintf(buf+len, "------------------------------------------------\n"); for (i = 0 ; i < NUM_IOP_CHAN ; i++) { len += sprintf(buf+len, "%2d %10s %10s %s\n", i, iop_chan_state(iop_readb(iop, IOP_ADDR_SEND_STATE+i)), iop_chan_state(iop_readb(iop, IOP_ADDR_RECV_STATE+i)), iop_listeners[iop_num][i].handler? iop_listeners[iop_num][i].devname : ""); } len += sprintf(buf+len, "\n"); return len; }
static void iop_handle_recv(uint iop_num, uint chan) { volatile struct mac_iop *iop = iop_base[iop_num]; int i,offset; struct iop_msg *msg; #ifdef DEBUG_IOP printk("iop_handle_recv: iop %d channel %d\n", iop_num, chan); #endif msg = iop_alloc_msg(); msg->iop_num = iop_num; msg->channel = chan; msg->status = IOP_MSGSTATUS_UNSOL; msg->handler = iop_listeners[iop_num][chan].handler; offset = IOP_ADDR_RECV_MSG + (chan * IOP_MSG_LEN); for (i = 0 ; i < IOP_MSG_LEN ; i++, offset++) { msg->message[i] = iop_readb(iop, offset); } iop_writeb(iop, IOP_ADDR_RECV_STATE + chan, IOP_MSG_RCVD); /* If there is a listener, call it now. Otherwise complete */ /* the message ourselves to avoid possible stalls. */ if (msg->handler) { (*msg->handler)(msg); } else { #ifdef DEBUG_IOP printk("iop_handle_recv: unclaimed message on iop %d channel %d\n", iop_num, chan); printk("iop_handle_recv:"); for (i = 0 ; i < IOP_MSG_LEN ; i++) { printk(" %02X", (uint) msg->message[i]); } printk("\n"); #endif iop_complete_message(msg); } }