⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 via-cuda.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (sync) {	while (!req->complete)	    cuda_poll();    }    return 0;}/* Enable/disable autopolling */static intcuda_adb_autopoll(int devs){    struct adb_request req;    if ((via == NULL) || !cuda_fully_inited)	return -ENXIO;    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0));    while (!req.complete)	cuda_poll();    return 0;}/* Reset adb bus - how do we do this?? */static intcuda_reset_adb_bus(void){    struct adb_request req;    if ((via == NULL) || !cuda_fully_inited)	return -ENXIO;    cuda_request(&req, NULL, 2, ADB_PACKET, 0);		/* maybe? */    while (!req.complete)	cuda_poll();    return 0;}#endif /* CONFIG_ADB *//* Construct and send a cuda request */intcuda_request(struct adb_request *req, void (*done)(struct adb_request *),	     int nbytes, ...){    va_list list;    int i;    if (via == NULL) {	req->complete = 1;	return -ENXIO;    }    req->nbytes = nbytes;    req->done = done;    va_start(list, nbytes);    for (i = 0; i < nbytes; ++i)	req->data[i] = va_arg(list, int);    va_end(list);    req->reply_expected = 1;    return cuda_write(req);}static intcuda_write(struct adb_request *req){    unsigned long flags;    if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) {	req->complete = 1;	return -EINVAL;    }    req->next = NULL;    req->sent = 0;    req->complete = 0;    req->reply_len = 0;    spin_lock_irqsave(&cuda_lock, flags);    if (current_req != 0) {	last_req->next = req;	last_req = req;    } else {	current_req = req;	last_req = req;	if (cuda_state == idle)	    cuda_start();    }    spin_unlock_irqrestore(&cuda_lock, flags);    return 0;}static voidcuda_start(void){    struct adb_request *req;    /* assert cuda_state == idle */    /* get the packet to send */    req = current_req;    if (req == 0)	return;    if ((in_8(&via[B]) & TREQ) == 0)	return;			/* a byte is coming in from the CUDA */    /* set the shift register to shift out and send a byte */    out_8(&via[ACR], in_8(&via[ACR]) | SR_OUT);    out_8(&via[SR], req->data[0]);    out_8(&via[B], in_8(&via[B]) & ~TIP);    cuda_state = sent_first_byte;}voidcuda_poll(void){    /* cuda_interrupt only takes a normal lock, we disable     * interrupts here to avoid re-entering and thus deadlocking.     */    disable_irq(cuda_irq);    cuda_interrupt(0, NULL);    enable_irq(cuda_irq);}static irqreturn_tcuda_interrupt(int irq, void *arg){    int status;    struct adb_request *req = NULL;    unsigned char ibuf[16];    int ibuf_len = 0;    int complete = 0;        spin_lock(&cuda_lock);    /* On powermacs, this handler is registered for the VIA IRQ. But it uses     * just the shift register IRQ -- other VIA interrupt sources are disabled.     * On m68k macs, the VIA IRQ sources are dispatched individually. Unless     * we are polling, the shift register IRQ flag has already been cleared.     */#ifdef CONFIG_MAC    if (!arg)#endif    {        if ((in_8(&via[IFR]) & SR_INT) == 0) {            spin_unlock(&cuda_lock);            return IRQ_NONE;        } else {            out_8(&via[IFR], SR_INT);        }    }        status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);    /* printk("cuda_interrupt: state=%d status=%x\n", cuda_state, status); */    switch (cuda_state) {    case idle:	/* CUDA has sent us the first byte of data - unsolicited */	if (status != TREQ)	    printk("cuda: state=idle, status=%x\n", status);	(void)in_8(&via[SR]);	out_8(&via[B], in_8(&via[B]) & ~TIP);	cuda_state = reading;	reply_ptr = cuda_rbuf;	reading_reply = 0;	break;    case awaiting_reply:	/* CUDA has sent us the first byte of data of a reply */	if (status != TREQ)	    printk("cuda: state=awaiting_reply, status=%x\n", status);	(void)in_8(&via[SR]);	out_8(&via[B], in_8(&via[B]) & ~TIP);	cuda_state = reading;	reply_ptr = current_req->reply;	reading_reply = 1;	break;    case sent_first_byte:	if (status == TREQ + TIP + SR_OUT) {	    /* collision */	    out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);	    (void)in_8(&via[SR]);	    out_8(&via[B], in_8(&via[B]) | TIP | TACK);	    cuda_state = idle;	} else {	    /* assert status == TIP + SR_OUT */	    if (status != TIP + SR_OUT)		printk("cuda: state=sent_first_byte status=%x\n", status);	    out_8(&via[SR], current_req->data[1]);	    out_8(&via[B], in_8(&via[B]) ^ TACK);	    data_index = 2;	    cuda_state = sending;	}	break;    case sending:	req = current_req;	if (data_index >= req->nbytes) {	    out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);	    (void)in_8(&via[SR]);	    out_8(&via[B], in_8(&via[B]) | TACK | TIP);	    req->sent = 1;	    if (req->reply_expected) {		cuda_state = awaiting_reply;	    } else {		current_req = req->next;		complete = 1;		/* not sure about this */		cuda_state = idle;		cuda_start();	    }	} else {	    out_8(&via[SR], req->data[data_index++]);	    out_8(&via[B], in_8(&via[B]) ^ TACK);	}	break;    case reading:	*reply_ptr++ = in_8(&via[SR]);	if (status == TIP) {	    /* that's all folks */	    out_8(&via[B], in_8(&via[B]) | TACK | TIP);	    cuda_state = read_done;	} else {	    /* assert status == TIP | TREQ */	    if (status != TIP + TREQ)		printk("cuda: state=reading status=%x\n", status);	    out_8(&via[B], in_8(&via[B]) ^ TACK);	}	break;    case read_done:	(void)in_8(&via[SR]);	if (reading_reply) {	    req = current_req;	    req->reply_len = reply_ptr - req->reply;	    if (req->data[0] == ADB_PACKET) {		/* Have to adjust the reply from ADB commands */		if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) {		    /* the 0x2 bit indicates no response */		    req->reply_len = 0;		} else {		    /* leave just the command and result bytes in the reply */		    req->reply_len -= 2;		    memmove(req->reply, req->reply + 2, req->reply_len);		}	    }	    current_req = req->next;	    complete = 1;	} else {	    /* This is tricky. We must break the spinlock to call	     * cuda_input. However, doing so means we might get	     * re-entered from another CPU getting an interrupt	     * or calling cuda_poll(). I ended up using the stack	     * (it's only for 16 bytes) and moving the actual	     * call to cuda_input to outside of the lock.	     */	    ibuf_len = reply_ptr - cuda_rbuf;	    memcpy(ibuf, cuda_rbuf, ibuf_len);	}	if (status == TREQ) {	    out_8(&via[B], in_8(&via[B]) & ~TIP);	    cuda_state = reading;	    reply_ptr = cuda_rbuf;	    reading_reply = 0;	} else {	    cuda_state = idle;	    cuda_start();	}	break;    default:	printk("cuda_interrupt: unknown cuda_state %d?\n", cuda_state);    }    spin_unlock(&cuda_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)	cuda_input(ibuf, ibuf_len);    return IRQ_HANDLED;}static voidcuda_input(unsigned char *buf, int nb){    int i;    switch (buf[0]) {    case ADB_PACKET:#ifdef CONFIG_XMON	if (nb == 5 && buf[2] == 0x2c) {	    extern int xmon_wants_key, xmon_adb_keycode;	    if (xmon_wants_key) {		xmon_adb_keycode = buf[3];		return;	    }	}#endif /* CONFIG_XMON */#ifdef CONFIG_ADB	adb_input(buf+2, nb-2, buf[1] & 0x40);#endif /* CONFIG_ADB */	break;    default:	printk("data from cuda (%d bytes):", nb);	for (i = 0; i < nb; ++i)	    printk(" %.2x", buf[i]);	printk("\n");    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -