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}
v5.4
  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)
 70		(*req->done)(req);
 71	adb_iop_state = state;
 
 
 72}
 73
 74/*
 75 * Completion routine for ADB commands sent to the IOP.
 76 *
 77 * This will be called when a packet has been successfully sent.
 78 */
 79
 80static void adb_iop_complete(struct iop_msg *msg)
 81{
 82	struct adb_request *req;
 83	unsigned long flags;
 84
 85	local_irq_save(flags);
 86
 87	req = current_req;
 88	if ((adb_iop_state == sending) && req && req->reply_expected) {
 89		adb_iop_state = awaiting_reply;
 90	}
 
 91
 92	local_irq_restore(flags);
 93}
 94
 95/*
 96 * Listen for ADB messages from the IOP.
 97 *
 98 * This will be called when unsolicited messages (usually replies to TALK
 99 * commands or autopoll packets) are received.
100 */
101
102static void adb_iop_listen(struct iop_msg *msg)
103{
104	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
105	struct adb_request *req;
106	unsigned long flags;
107#ifdef DEBUG_ADB_IOP
108	int i;
109#endif
110
111	local_irq_save(flags);
112
113	req = current_req;
 
 
 
 
 
 
 
114
115#ifdef DEBUG_ADB_IOP
116	printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req,
117	       (uint)amsg->count + 2, (uint)amsg->flags, (uint)amsg->cmd);
118	for (i = 0; i < amsg->count; i++)
119		printk(" %02X", (uint)amsg->data[i]);
120	printk("\n");
121#endif
122
123	/* Handle a timeout. Timeout packets seem to occur even after */
124	/* we've gotten a valid reply to a TALK, so I'm assuming that */
125	/* a "timeout" is actually more like an "end-of-data" signal. */
126	/* We need to send back a timeout packet to the IOP to shut   */
127	/* it up, plus complete the current request, if any.          */
128
129	if (amsg->flags & ADB_IOP_TIMEOUT) {
130		msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL;
131		msg->reply[1] = 0;
132		msg->reply[2] = 0;
133		if (req && (adb_iop_state != idle)) {
134			adb_iop_end_req(req, idle);
135		}
136	} else {
137		/* TODO: is it possible for more than one chunk of data  */
138		/*       to arrive before the timeout? If so we need to */
139		/*       use reply_ptr here like the other drivers do.  */
140		if ((adb_iop_state == awaiting_reply) &&
141		    (amsg->flags & ADB_IOP_EXPLICIT)) {
142			req->reply_len = amsg->count + 1;
143			memcpy(req->reply, &amsg->cmd, req->reply_len);
144		} else {
145			adb_input(&amsg->cmd, amsg->count + 1,
146				  amsg->flags & ADB_IOP_AUTOPOLL);
147		}
148		memcpy(msg->reply, msg->message, IOP_MSG_LEN);
 
 
149	}
 
 
150	iop_complete_message(msg);
 
 
 
 
151	local_irq_restore(flags);
152}
153
154/*
155 * Start sending an ADB packet, IOP style
156 *
157 * There isn't much to do other than hand the packet over to the IOP
158 * after encapsulating it in an adb_iopmsg.
159 */
160
161static void adb_iop_start(void)
162{
163	unsigned long flags;
164	struct adb_request *req;
165	struct adb_iopmsg amsg;
166#ifdef DEBUG_ADB_IOP
167	int i;
168#endif
169
170	/* get the packet to send */
171	req = current_req;
172	if (!req)
173		return;
174
175	local_irq_save(flags);
176
177#ifdef DEBUG_ADB_IOP
178	printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes);
179	for (i = 0; i < req->nbytes; i++)
180		printk(" %02X", (uint)req->data[i]);
181	printk("\n");
182#endif
183
184	/* The IOP takes MacII-style packets, so */
185	/* strip the initial ADB_PACKET byte.    */
186
187	amsg.flags = ADB_IOP_EXPLICIT;
188	amsg.count = req->nbytes - 2;
189
190	/* amsg.data immediately follows amsg.cmd, effectively making */
191	/* amsg.cmd a pointer to the beginning of a full ADB packet.  */
 
192	memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
193
194	req->sent = 1;
195	adb_iop_state = sending;
196	local_irq_restore(flags);
197
198	/* Now send it. The IOP manager will call adb_iop_complete */
199	/* when the packet has been sent.                          */
200
 
 
 
201	iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg,
202			 adb_iop_complete);
203}
204
205int adb_iop_probe(void)
206{
207	if (!iop_ism_present)
208		return -ENODEV;
209	return 0;
210}
211
212int adb_iop_init(void)
213{
214	pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n");
215	iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
216	return 0;
217}
218
219int adb_iop_send_request(struct adb_request *req, int sync)
220{
221	int err;
222
223	err = adb_iop_write(req);
224	if (err)
225		return err;
226
227	if (sync) {
228		while (!req->complete)
229			adb_iop_poll();
230	}
231	return 0;
232}
233
234static int adb_iop_write(struct adb_request *req)
235{
236	unsigned long flags;
237
238	if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
239		req->complete = 1;
240		return -EINVAL;
241	}
242
243	local_irq_save(flags);
244
245	req->next = NULL;
246	req->sent = 0;
247	req->complete = 0;
248	req->reply_len = 0;
249
250	if (current_req != 0) {
 
 
251		last_req->next = req;
252		last_req = req;
253	} else {
254		current_req = req;
255		last_req = req;
256	}
257
 
 
 
258	local_irq_restore(flags);
259
260	if (adb_iop_state == idle)
261		adb_iop_start();
262	return 0;
263}
264
265int adb_iop_autopoll(int devs)
266{
267	/* TODO: how do we enable/disable autopoll? */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268	return 0;
269}
270
271void adb_iop_poll(void)
272{
273	if (adb_iop_state == idle)
274		adb_iop_start();
275	iop_ism_irq_poll(ADB_IOP);
276}
277
278int adb_iop_reset_bus(void)
279{
280	struct adb_request req = {
281		.reply_expected = 0,
282		.nbytes = 2,
283		.data = { ADB_PACKET, 0 },
284	};
285
286	adb_iop_write(&req);
287	while (!req.complete) {
288		adb_iop_poll();
289		schedule();
290	}
291
292	return 0;
293}