static irqreturn_t macio_adb_interrupt()

in macio-adb.c [200:273]


static irqreturn_t macio_adb_interrupt(int irq, void *arg)
{
	int i, n, err;
	struct adb_request *req = NULL;
	unsigned char ibuf[16];
	int ibuf_len = 0;
	int complete = 0;
	int autopoll = 0;
	int handled = 0;

	spin_lock(&macio_lock);
	if (in_8(&adb->intr.r) & TAG) {
		handled = 1;
		if ((req = current_req) != 0) {
			/* put the current request in */
			for (i = 0; i < req->nbytes; ++i)
				out_8(&adb->data[i].r, req->data[i]);
			out_8(&adb->dcount.r, req->nbytes & HMB);
			req->sent = 1;
			if (req->reply_expected) {
				out_8(&adb->ctrl.r, DTB + CRE);
			} else {
				out_8(&adb->ctrl.r, DTB);
				current_req = req->next;
				complete = 1;
				if (current_req)
					out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
			}
		}
		out_8(&adb->intr.r, 0);
	}

	if (in_8(&adb->intr.r) & DFB) {
		handled = 1;
		err = in_8(&adb->error.r);
		if (current_req && current_req->sent) {
			/* this is the response to a command */
			req = current_req;
			if (err == 0) {
				req->reply_len = in_8(&adb->dcount.r) & HMB;
				for (i = 0; i < req->reply_len; ++i)
					req->reply[i] = in_8(&adb->data[i].r);
			}
			current_req = req->next;
			complete = 1;
			if (current_req)
				out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
		} else if (err == 0) {
			/* autopoll data */
			n = in_8(&adb->dcount.r) & HMB;
			for (i = 0; i < n; ++i)
				ibuf[i] = in_8(&adb->data[i].r);
			ibuf_len = n;
			autopoll = (in_8(&adb->dcount.r) & APD) != 0;
		}
		out_8(&adb->error.r, 0);
		out_8(&adb->intr.r, 0);
	}
	spin_unlock(&macio_lock);
	if (complete && req) {
	    void (*done)(struct adb_request *) = req->done;
	    mb();
	    req->complete = 1;
	    /* Here, we assume that if the request has a done member, the
    	     * struct request will survive to setting req->complete to 1
	     */
	    if (done)
		(*done)(req);
	}
	if (ibuf_len)
		adb_input(ibuf, ibuf_len, autopoll);

	return IRQ_RETVAL(handled);
}