Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * I/O Processor (IOP) ADB Driver
  4 * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org)
  5 * Based on via-cuda.c by Paul Mackerras.
  6 *
  7 * 1999-07-01 (jmt) - First implementation for new driver architecture.
  8 *
  9 * 1999-07-31 (jmt) - First working version.
 
 
 
 
 10 */
 11
 12#include <linux/types.h>
 13#include <linux/kernel.h>
 14#include <linux/mm.h>
 15#include <linux/delay.h>
 16#include <linux/init.h>
 
 17
 18#include <asm/macintosh.h>
 19#include <asm/macints.h>
 20#include <asm/mac_iop.h>
 
 21#include <asm/adb_iop.h>
 22
 23#include <linux/adb.h>
 
 
 24
 25static struct adb_request *current_req;
 26static struct adb_request *last_req;
 27static unsigned int autopoll_devs;
 
 
 
 28
 29static enum adb_iop_state {
 30	idle,
 31	sending,
 32	awaiting_reply
 33} adb_iop_state;
 34
 35static void adb_iop_start(void);
 36static int adb_iop_probe(void);
 37static int adb_iop_init(void);
 38static int adb_iop_send_request(struct adb_request *, int);
 39static int adb_iop_write(struct adb_request *);
 40static int adb_iop_autopoll(int);
 41static void adb_iop_poll(void);
 42static int adb_iop_reset_bus(void);
 43
 44struct adb_driver adb_iop_driver = {
 45	.name         = "ISM IOP",
 46	.probe        = adb_iop_probe,
 47	.init         = adb_iop_init,
 48	.send_request = adb_iop_send_request,
 49	.autopoll     = adb_iop_autopoll,
 50	.poll         = adb_iop_poll,
 51	.reset_bus    = adb_iop_reset_bus
 52};
 53
 54static void adb_iop_done(void)
 55{
 56	struct adb_request *req = current_req;
 57
 58	adb_iop_state = idle;
 59
 60	req->complete = 1;
 61	current_req = req->next;
 62	if (req->done)
 63		(*req->done)(req);
 64
 65	if (adb_iop_state == idle)
 66		adb_iop_start();
 67}
 68
 69/*
 70 * Completion routine for ADB commands sent to the IOP.
 71 *
 72 * This will be called when a packet has been successfully sent.
 73 */
 74
 75static void adb_iop_complete(struct iop_msg *msg)
 76{
 
 77	unsigned long flags;
 78
 79	local_irq_save(flags);
 80
 81	if (current_req->reply_expected)
 
 82		adb_iop_state = awaiting_reply;
 83	else
 84		adb_iop_done();
 85
 86	local_irq_restore(flags);
 87}
 88
 89/*
 90 * Listen for ADB messages from the IOP.
 91 *
 92 * This will be called when unsolicited messages (usually replies to TALK
 93 * commands or autopoll packets) are received.
 94 */
 95
 96static void adb_iop_listen(struct iop_msg *msg)
 97{
 98	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
 
 99	unsigned long flags;
100	bool req_done = false;
 
 
101
102	local_irq_save(flags);
103
104	/* Handle a timeout. Timeout packets seem to occur even after
105	 * we've gotten a valid reply to a TALK, presumably because of
106	 * autopolling.
107	 */
108
109	if (amsg->flags & ADB_IOP_EXPLICIT) {
110		if (adb_iop_state == awaiting_reply) {
111			struct adb_request *req = current_req;
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113			req->reply_len = amsg->count + 1;
114			memcpy(req->reply, &amsg->cmd, req->reply_len);
115
116			req_done = true;
 
117		}
118	} else if (!(amsg->flags & ADB_IOP_TIMEOUT)) {
119		adb_input(&amsg->cmd, amsg->count + 1,
120			  amsg->flags & ADB_IOP_AUTOPOLL);
121	}
122
123	msg->reply[0] = autopoll_devs ? ADB_IOP_AUTOPOLL : 0;
124	iop_complete_message(msg);
125
126	if (req_done)
127		adb_iop_done();
128
129	local_irq_restore(flags);
130}
131
132/*
133 * Start sending an ADB packet, IOP style
134 *
135 * There isn't much to do other than hand the packet over to the IOP
136 * after encapsulating it in an adb_iopmsg.
137 */
138
139static void adb_iop_start(void)
140{
 
141	struct adb_request *req;
142	struct adb_iopmsg amsg;
 
 
 
143
144	/* get the packet to send */
145	req = current_req;
146	if (!req)
147		return;
 
 
 
 
 
 
 
 
 
 
 
148
149	/* The IOP takes MacII-style packets, so strip the initial
150	 * ADB_PACKET byte.
151	 */
152	amsg.flags = ADB_IOP_EXPLICIT;
153	amsg.count = req->nbytes - 2;
154
155	/* amsg.data immediately follows amsg.cmd, effectively making
156	 * &amsg.cmd a pointer to the beginning of a full ADB packet.
157	 */
158	memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
159
160	req->sent = 1;
161	adb_iop_state = sending;
 
162
163	/* Now send it. The IOP manager will call adb_iop_complete
164	 * when the message has been sent.
165	 */
166	iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg,
167			 adb_iop_complete);
168}
169
170static int adb_iop_probe(void)
171{
172	if (!iop_ism_present)
173		return -ENODEV;
174	return 0;
175}
176
177static int adb_iop_init(void)
178{
179	pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n");
180	iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
181	return 0;
182}
183
184static int adb_iop_send_request(struct adb_request *req, int sync)
185{
186	int err;
187
188	err = adb_iop_write(req);
189	if (err)
190		return err;
191
192	if (sync) {
193		while (!req->complete)
194			adb_iop_poll();
195	}
196	return 0;
197}
198
199static int adb_iop_write(struct adb_request *req)
200{
201	unsigned long flags;
202
203	if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
204		req->complete = 1;
205		return -EINVAL;
206	}
207
 
 
208	req->next = NULL;
209	req->sent = 0;
210	req->complete = 0;
211	req->reply_len = 0;
212
213	local_irq_save(flags);
214
215	if (current_req) {
216		last_req->next = req;
217		last_req = req;
218	} else {
219		current_req = req;
220		last_req = req;
221	}
222
223	if (adb_iop_state == idle)
224		adb_iop_start();
225
226	local_irq_restore(flags);
227
228	return 0;
229}
230
231static void adb_iop_set_ap_complete(struct iop_msg *msg)
232{
233	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
234
235	autopoll_devs = (amsg->data[1] << 8) | amsg->data[0];
236}
237
238static int adb_iop_autopoll(int devs)
239{
240	struct adb_iopmsg amsg;
241	unsigned long flags;
242	unsigned int mask = (unsigned int)devs & 0xFFFE;
243
244	local_irq_save(flags);
245
246	amsg.flags = ADB_IOP_SET_AUTOPOLL | (mask ? ADB_IOP_AUTOPOLL : 0);
247	amsg.count = 2;
248	amsg.cmd = 0;
249	amsg.data[0] = mask & 0xFF;
250	amsg.data[1] = (mask >> 8) & 0xFF;
251
252	iop_send_message(ADB_IOP, ADB_CHAN, NULL, sizeof(amsg), (__u8 *)&amsg,
253			 adb_iop_set_ap_complete);
254
255	local_irq_restore(flags);
256
257	return 0;
258}
259
260static void adb_iop_poll(void)
261{
 
262	iop_ism_irq_poll(ADB_IOP);
263}
264
265static int adb_iop_reset_bus(void)
266{
267	struct adb_request req;
268
269	/* Command = 0, Address = ignored */
270	adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET);
271	adb_iop_send_request(&req, 1);
272
273	/* Don't want any more requests during the Global Reset low time. */
274	mdelay(3);
 
 
 
275
276	return 0;
277}
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * I/O Processor (IOP) ADB Driver
  4 * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org)
  5 * Based on via-cuda.c by Paul Mackerras.
  6 *
  7 * 1999-07-01 (jmt) - First implementation for new driver architecture.
  8 *
  9 * 1999-07-31 (jmt) - First working version.
 10 *
 11 * TODO:
 12 *
 13 * o Implement SRQ handling.
 14 */
 15
 16#include <linux/types.h>
 17#include <linux/kernel.h>
 18#include <linux/mm.h>
 19#include <linux/delay.h>
 20#include <linux/init.h>
 21#include <linux/proc_fs.h>
 22
 23#include <asm/macintosh.h> 
 24#include <asm/macints.h> 
 25#include <asm/mac_iop.h>
 26#include <asm/mac_oss.h>
 27#include <asm/adb_iop.h>
 28
 29#include <linux/adb.h> 
 30
 31/*#define DEBUG_ADB_IOP*/
 32
 33static struct adb_request *current_req;
 34static struct adb_request *last_req;
 35#if 0
 36static unsigned char reply_buff[16];
 37static unsigned char *reply_ptr;
 38#endif
 39
 40static enum adb_iop_state {
 41    idle,
 42    sending,
 43    awaiting_reply
 44} adb_iop_state;
 45
 46static void adb_iop_start(void);
 47static int adb_iop_probe(void);
 48static int adb_iop_init(void);
 49static int adb_iop_send_request(struct adb_request *, int);
 50static int adb_iop_write(struct adb_request *);
 51static int adb_iop_autopoll(int);
 52static void adb_iop_poll(void);
 53static int adb_iop_reset_bus(void);
 54
 55struct adb_driver adb_iop_driver = {
 56	.name         = "ISM IOP",
 57	.probe        = adb_iop_probe,
 58	.init         = adb_iop_init,
 59	.send_request = adb_iop_send_request,
 60	.autopoll     = adb_iop_autopoll,
 61	.poll         = adb_iop_poll,
 62	.reset_bus    = adb_iop_reset_bus
 63};
 64
 65static void adb_iop_end_req(struct adb_request *req, int state)
 66{
 
 
 
 
 67	req->complete = 1;
 68	current_req = req->next;
 69	if (req->done) (*req->done)(req);
 70	adb_iop_state = state;
 
 
 
 71}
 72
 73/*
 74 * Completion routine for ADB commands sent to the IOP.
 75 *
 76 * This will be called when a packet has been successfully sent.
 77 */
 78
 79static void adb_iop_complete(struct iop_msg *msg)
 80{
 81	struct adb_request *req;
 82	unsigned long flags;
 83
 84	local_irq_save(flags);
 85
 86	req = current_req;
 87	if ((adb_iop_state == sending) && req && req->reply_expected) {
 88		adb_iop_state = awaiting_reply;
 89	}
 
 90
 91	local_irq_restore(flags);
 92}
 93
 94/*
 95 * Listen for ADB messages from the IOP.
 96 *
 97 * This will be called when unsolicited messages (usually replies to TALK
 98 * commands or autopoll packets) are received.
 99 */
100
101static void adb_iop_listen(struct iop_msg *msg)
102{
103	struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message;
104	struct adb_request *req;
105	unsigned long flags;
106#ifdef DEBUG_ADB_IOP
107	int i;
108#endif
109
110	local_irq_save(flags);
111
112	req = current_req;
 
 
 
 
 
 
 
113
114#ifdef DEBUG_ADB_IOP
115	printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req,
116		(uint) amsg->count + 2, (uint) amsg->flags, (uint) amsg->cmd);
117	for (i = 0; i < amsg->count; i++)
118		printk(" %02X", (uint) amsg->data[i]);
119	printk("\n");
120#endif
121
122	/* Handle a timeout. Timeout packets seem to occur even after */
123	/* we've gotten a valid reply to a TALK, so I'm assuming that */
124	/* a "timeout" is actually more like an "end-of-data" signal. */
125	/* We need to send back a timeout packet to the IOP to shut   */
126	/* it up, plus complete the current request, if any.          */
127
128	if (amsg->flags & ADB_IOP_TIMEOUT) {
129		msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL;
130		msg->reply[1] = 0;
131		msg->reply[2] = 0;
132		if (req && (adb_iop_state != idle)) {
133			adb_iop_end_req(req, idle);
134		}
135	} else {
136		/* TODO: is it possible for more than one chunk of data  */
137		/*       to arrive before the timeout? If so we need to */
138		/*       use reply_ptr here like the other drivers do.  */
139		if ((adb_iop_state == awaiting_reply) &&
140		    (amsg->flags & ADB_IOP_EXPLICIT)) {
141			req->reply_len = amsg->count + 1;
142			memcpy(req->reply, &amsg->cmd, req->reply_len);
143		} else {
144			adb_input(&amsg->cmd, amsg->count + 1,
145				  amsg->flags & ADB_IOP_AUTOPOLL);
146		}
147		memcpy(msg->reply, msg->message, IOP_MSG_LEN);
 
 
148	}
 
 
149	iop_complete_message(msg);
 
 
 
 
150	local_irq_restore(flags);
151}
152
153/*
154 * Start sending an ADB packet, IOP style
155 *
156 * There isn't much to do other than hand the packet over to the IOP
157 * after encapsulating it in an adb_iopmsg.
158 */
159
160static void adb_iop_start(void)
161{
162	unsigned long flags;
163	struct adb_request *req;
164	struct adb_iopmsg amsg;
165#ifdef DEBUG_ADB_IOP
166	int i;
167#endif
168
169	/* get the packet to send */
170	req = current_req;
171	if (!req) return;
172
173	local_irq_save(flags);
174
175#ifdef DEBUG_ADB_IOP
176	printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes);
177	for (i = 0 ; i < req->nbytes ; i++)
178		printk(" %02X", (uint) req->data[i]);
179	printk("\n");
180#endif
181
182	/* The IOP takes MacII-style packets, so */
183	/* strip the initial ADB_PACKET byte.    */
184
 
 
 
185	amsg.flags = ADB_IOP_EXPLICIT;
186	amsg.count = req->nbytes - 2;
187
188	/* amsg.data immediately follows amsg.cmd, effectively making */
189	/* amsg.cmd a pointer to the beginning of a full ADB packet.  */
 
190	memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
191
192	req->sent = 1;
193	adb_iop_state = sending;
194	local_irq_restore(flags);
195
196	/* Now send it. The IOP manager will call adb_iop_complete */
197	/* when the packet has been sent.                          */
198
199	iop_send_message(ADB_IOP, ADB_CHAN, req,
200			 sizeof(amsg), (__u8 *) &amsg, adb_iop_complete);
201}
202
203int adb_iop_probe(void)
204{
205	if (!iop_ism_present) return -ENODEV;
 
206	return 0;
207}
208
209int adb_iop_init(void)
210{
211	printk("adb: IOP ISM driver v0.4 for Unified ADB.\n");
212	iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
213	return 0;
214}
215
216int adb_iop_send_request(struct adb_request *req, int sync)
217{
218	int err;
219
220	err = adb_iop_write(req);
221	if (err) return err;
 
222
223	if (sync) {
224		while (!req->complete) adb_iop_poll();
 
225	}
226	return 0;
227}
228
229static int adb_iop_write(struct adb_request *req)
230{
231	unsigned long flags;
232
233	if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
234		req->complete = 1;
235		return -EINVAL;
236	}
237
238	local_irq_save(flags);
239
240	req->next = NULL;
241	req->sent = 0;
242	req->complete = 0;
243	req->reply_len = 0;
244
245	if (current_req != 0) {
 
 
246		last_req->next = req;
247		last_req = req;
248	} else {
249		current_req = req;
250		last_req = req;
251	}
252
 
 
 
253	local_irq_restore(flags);
254	if (adb_iop_state == idle) adb_iop_start();
255	return 0;
256}
257
258int adb_iop_autopoll(int devs)
 
 
 
 
 
 
 
259{
260	/* TODO: how do we enable/disable autopoll? */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261	return 0;
262}
263
264void adb_iop_poll(void)
265{
266	if (adb_iop_state == idle) adb_iop_start();
267	iop_ism_irq_poll(ADB_IOP);
268}
269
270int adb_iop_reset_bus(void)
271{
272	struct adb_request req = {
273		.reply_expected = 0,
274		.nbytes = 2,
275		.data = { ADB_PACKET, 0 },
276	};
277
278	adb_iop_write(&req);
279	while (!req.complete) {
280		adb_iop_poll();
281		schedule();
282	}
283
284	return 0;
285}