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}
v6.2
  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#include <asm/unaligned.h>
 23
 24#include <linux/adb.h>
 25
 26static struct adb_request *current_req;
 27static struct adb_request *last_req;
 28static unsigned int autopoll_devs;
 29static u8 autopoll_addr;
 30
 31static enum adb_iop_state {
 32	idle,
 33	sending,
 34	awaiting_reply
 35} adb_iop_state;
 36
 37static void adb_iop_start(void);
 38static int adb_iop_probe(void);
 39static int adb_iop_init(void);
 40static int adb_iop_send_request(struct adb_request *, int);
 41static int adb_iop_write(struct adb_request *);
 42static int adb_iop_autopoll(int);
 43static void adb_iop_poll(void);
 44static int adb_iop_reset_bus(void);
 45
 46/* ADB command byte structure */
 47#define ADDR_MASK       0xF0
 48#define OP_MASK         0x0C
 49#define TALK            0x0C
 50
 51struct adb_driver adb_iop_driver = {
 52	.name         = "ISM IOP",
 53	.probe        = adb_iop_probe,
 54	.init         = adb_iop_init,
 55	.send_request = adb_iop_send_request,
 56	.autopoll     = adb_iop_autopoll,
 57	.poll         = adb_iop_poll,
 58	.reset_bus    = adb_iop_reset_bus
 59};
 60
 61static void adb_iop_done(void)
 62{
 63	struct adb_request *req = current_req;
 64
 65	adb_iop_state = idle;
 66
 67	req->complete = 1;
 68	current_req = req->next;
 69	if (req->done)
 70		(*req->done)(req);
 71
 72	if (adb_iop_state == idle)
 73		adb_iop_start();
 74}
 75
 76/*
 77 * Completion routine for ADB commands sent to the IOP.
 78 *
 79 * This will be called when a packet has been successfully sent.
 80 */
 81
 82static void adb_iop_complete(struct iop_msg *msg)
 83{
 84	unsigned long flags;
 85
 86	local_irq_save(flags);
 87
 88	adb_iop_state = awaiting_reply;
 
 
 
 89
 90	local_irq_restore(flags);
 91}
 92
 93/*
 94 * Listen for ADB messages from the IOP.
 95 *
 96 * This will be called when unsolicited IOP messages are received.
 97 * These IOP messages can carry ADB autopoll responses and also occur
 98 * after explicit ADB commands.
 99 */
100
101static void adb_iop_listen(struct iop_msg *msg)
102{
103	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
104	u8 addr = (amsg->cmd & ADDR_MASK) >> 4;
105	u8 op = amsg->cmd & OP_MASK;
106	unsigned long flags;
107	bool req_done = false;
108
109	local_irq_save(flags);
110
111	/* Responses to Talk commands may be unsolicited as they are
112	 * produced when the IOP polls devices. They are mostly timeouts.
 
113	 */
114	if (op == TALK && ((1 << addr) & autopoll_devs))
115		autopoll_addr = addr;
116
117	switch (amsg->flags & (ADB_IOP_EXPLICIT |
118			       ADB_IOP_AUTOPOLL |
119			       ADB_IOP_TIMEOUT)) {
120	case ADB_IOP_EXPLICIT:
121	case ADB_IOP_EXPLICIT | ADB_IOP_TIMEOUT:
122		if (adb_iop_state == awaiting_reply) {
123			struct adb_request *req = current_req;
124
125			if (req->reply_expected) {
126				req->reply_len = amsg->count + 1;
127				memcpy(req->reply, &amsg->cmd, req->reply_len);
128			}
129
130			req_done = true;
131		}
132		break;
133	case ADB_IOP_AUTOPOLL:
134		if (((1 << addr) & autopoll_devs) &&
135		    amsg->cmd == ADB_READREG(addr, 0))
136			adb_input(&amsg->cmd, amsg->count + 1, 1);
137		break;
138	}
139	msg->reply[0] = autopoll_addr ? ADB_IOP_AUTOPOLL : 0;
140	msg->reply[1] = 0;
141	msg->reply[2] = autopoll_addr ? ADB_READREG(autopoll_addr, 0) : 0;
142	iop_complete_message(msg);
143
144	if (req_done)
145		adb_iop_done();
146
147	local_irq_restore(flags);
148}
149
150/*
151 * Start sending an ADB packet, IOP style
152 *
153 * There isn't much to do other than hand the packet over to the IOP
154 * after encapsulating it in an adb_iopmsg.
155 */
156
157static void adb_iop_start(void)
158{
159	struct adb_request *req;
160	struct adb_iopmsg amsg;
161
162	/* get the packet to send */
163	req = current_req;
164	if (!req)
165		return;
166
167	/* The IOP takes MacII-style packets, so strip the initial
168	 * ADB_PACKET byte.
169	 */
170	amsg.flags = ADB_IOP_EXPLICIT;
171	amsg.count = req->nbytes - 2;
172
173	/* amsg.data immediately follows amsg.cmd, effectively making
174	 * &amsg.cmd a pointer to the beginning of a full ADB packet.
175	 */
176	memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
177
178	req->sent = 1;
179	adb_iop_state = sending;
180
181	/* Now send it. The IOP manager will call adb_iop_complete
182	 * when the message has been sent.
183	 */
184	iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg,
185			 adb_iop_complete);
186}
187
188static int adb_iop_probe(void)
189{
190	if (!iop_ism_present)
191		return -ENODEV;
192	return 0;
193}
194
195static int adb_iop_init(void)
196{
197	pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n");
198	iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
199	return 0;
200}
201
202static int adb_iop_send_request(struct adb_request *req, int sync)
203{
204	int err;
205
206	err = adb_iop_write(req);
207	if (err)
208		return err;
209
210	if (sync) {
211		while (!req->complete)
212			adb_iop_poll();
213	}
214	return 0;
215}
216
217static int adb_iop_write(struct adb_request *req)
218{
219	unsigned long flags;
220
221	if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
222		req->complete = 1;
223		return -EINVAL;
224	}
225
226	req->next = NULL;
227	req->sent = 0;
228	req->complete = 0;
229	req->reply_len = 0;
230
231	local_irq_save(flags);
232
233	if (current_req) {
234		last_req->next = req;
235		last_req = req;
236	} else {
237		current_req = req;
238		last_req = req;
239	}
240
241	if (adb_iop_state == idle)
242		adb_iop_start();
243
244	local_irq_restore(flags);
245
246	return 0;
247}
248
249static void adb_iop_set_ap_complete(struct iop_msg *msg)
250{
251	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
252
253	autopoll_devs = get_unaligned_be16(amsg->data);
254	if (autopoll_devs & (1 << autopoll_addr))
255		return;
256	autopoll_addr = autopoll_devs ? (ffs(autopoll_devs) - 1) : 0;
257}
258
259static int adb_iop_autopoll(int devs)
260{
261	struct adb_iopmsg amsg;
262	unsigned long flags;
263	unsigned int mask = (unsigned int)devs & 0xFFFE;
264
265	local_irq_save(flags);
266
267	amsg.flags = ADB_IOP_SET_AUTOPOLL | (mask ? ADB_IOP_AUTOPOLL : 0);
268	amsg.count = 2;
269	amsg.cmd = 0;
270	put_unaligned_be16(mask, amsg.data);
 
271
272	iop_send_message(ADB_IOP, ADB_CHAN, NULL, sizeof(amsg), (__u8 *)&amsg,
273			 adb_iop_set_ap_complete);
274
275	local_irq_restore(flags);
276
277	return 0;
278}
279
280static void adb_iop_poll(void)
281{
282	iop_ism_irq_poll(ADB_IOP);
283}
284
285static int adb_iop_reset_bus(void)
286{
287	struct adb_request req;
288
289	/* Command = 0, Address = ignored */
290	adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET);
291	adb_iop_send_request(&req, 1);
292
293	/* Don't want any more requests during the Global Reset low time. */
294	mdelay(3);
295
296	return 0;
297}