Commit | Line | Data |
---|---|---|
2eae6bdc AS |
1 | /*********************************************************************************** |
2 | CED1401 usb driver. This basic loading is based on the usb-skeleton.c code that is: | |
3 | Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | |
4 | Copyright (C) 2012 Alois Schloegl <alois.schloegl@ist.ac.at> | |
5 | There is not a great deal of the skeleton left. | |
6 | ||
7 | All the remainder dealing specifically with the CED1401 is based on drivers written | |
8 | by CED for other systems (mainly Windows) and is: | |
9 | Copyright (C) 2010 Cambridge Electronic Design Ltd | |
10 | Author Greg P Smith (greg@ced.co.uk) | |
11 | ||
12 | This program is free software; you can redistribute it and/or | |
13 | modify it under the terms of the GNU General Public License | |
14 | as published by the Free Software Foundation; either version 2 | |
15 | of the License, or (at your option) any later version. | |
16 | ||
17 | This program is distributed in the hope that it will be useful, | |
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | GNU General Public License for more details. | |
21 | ||
22 | You should have received a copy of the GNU General Public License | |
23 | along with this program; if not, write to the Free Software | |
24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
25 | ||
2eae6bdc AS |
26 | Endpoints |
27 | ********* | |
28 | There are 4 endpoints plus the control endpoint in the standard interface | |
29 | provided by most 1401s. The control endpoint is used for standard USB requests, | |
30 | plus various CED-specific transactions such as start self test, debug and get | |
31 | the 1401 status. The other endpoints are: | |
32 | ||
33 | 1 Characters to the 1401 | |
34 | 2 Characters from the 1401 | |
35 | 3 Block data to the 1401 | |
36 | 4 Block data to the host. | |
37 | ||
38 | inside the driver these are indexed as an array from 0 to 3, transactions | |
39 | over the control endpoint are carried out using a separate mechanism. The | |
40 | use of the endpoints is mostly straightforward, with the driver issuing | |
41 | IO request packets (IRPs) as required to transfer data to and from the 1401. | |
42 | The handling of endpoint 2 is different because it is used for characters | |
43 | from the 1401, which can appear spontaneously and without any other driver | |
44 | activity - for example to repeatedly request DMA transfers in Spike2. The | |
45 | desired effect is achieved by using an interrupt endpoint which can be | |
46 | polled to see if it has data available, and writing the driver so that it | |
47 | always maintains a pending read IRP from that endpoint which will read the | |
48 | character data and terminate as soon as the 1401 makes data available. This | |
49 | works very well, some care is taken with when you kick off this character | |
50 | read IRP to avoid it being active when it is not wanted but generally it | |
51 | is running all the time. | |
52 | ||
53 | In the 2270, there are only three endpoints plus the control endpoint. In | |
54 | addition to the transactions mentioned above, the control endpoint is used | |
55 | to transfer character data to the 1401. The other endpoints are used as: | |
56 | ||
57 | 1 Characters from the 1401 | |
58 | 2 Block data to the 1401 | |
59 | 3 Block data to the host. | |
60 | ||
61 | The type of interface available is specified by the interface subclass field | |
62 | in the interface descriptor provided by the 1401. See the USB_INT_ constants | |
63 | for the values that this field can hold. | |
64 | ||
65 | **************************************************************************** | |
66 | Linux implementation | |
67 | ||
68 | Although Linux Device Drivers (3rd Edition) was a major source of information, | |
69 | it is very out of date. A lot of information was gleaned from the latest | |
70 | usb_skeleton.c code (you need to download the kernel sources to get this). | |
71 | ||
72 | To match the Windows version, everything is done using ioctl calls. All the | |
73 | device state is held in the DEVICE_EXTENSION (named to match Windows use). | |
74 | Block transfers are done by using get_user_pages() to pin down a list of | |
75 | pages that we hold a pointer to in the device driver. We also allocate a | |
76 | coherent transfer buffer of size STAGED_SZ (this must be a multiple of the | |
77 | bulk endpoint size so that the 1401 does not realise that we break large | |
78 | transfers down into smaller pieces). We use kmap_atomic() to get a kernel | |
79 | va for each page, as it is required, for copying; see CopyUserSpace(). | |
80 | ||
81 | All character and data transfers are done using asynchronous IO. All Urbs are | |
82 | tracked by anchoring them. Status and debug ioctls are implemented with the | |
83 | synchronous non-Urb based transfers. | |
84 | */ | |
85 | ||
86 | #include <linux/kernel.h> | |
87 | #include <linux/errno.h> | |
88 | #include <linux/usb.h> | |
89 | #include <linux/mutex.h> | |
90 | #include <linux/mm.h> | |
91 | #include <linux/highmem.h> | |
cd915200 GKH |
92 | #include <linux/slab.h> |
93 | #include <linux/module.h> | |
94 | #include <linux/kref.h> | |
95 | #include <linux/uaccess.h> | |
2eae6bdc | 96 | |
2eae6bdc AS |
97 | #include "usb1401.h" |
98 | ||
99 | /* Define these values to match your devices */ | |
100 | #define USB_CED_VENDOR_ID 0x0525 | |
101 | #define USB_CED_PRODUCT_ID 0xa0f0 | |
102 | ||
103 | /* table of devices that work with this driver */ | |
cd915200 GKH |
104 | static const struct usb_device_id ced_table[] = { |
105 | {USB_DEVICE(USB_CED_VENDOR_ID, USB_CED_PRODUCT_ID)}, | |
106 | {} /* Terminating entry */ | |
2eae6bdc | 107 | }; |
2eae6bdc | 108 | |
cd915200 | 109 | MODULE_DEVICE_TABLE(usb, ced_table); |
2eae6bdc AS |
110 | |
111 | /* Get a minor range for your devices from the usb maintainer */ | |
112 | #define USB_CED_MINOR_BASE 192 | |
113 | ||
114 | /* our private defines. if this grows any larger, use your own .h file */ | |
115 | #define MAX_TRANSFER (PAGE_SIZE - 512) | |
116 | /* MAX_TRANSFER is chosen so that the VM is not stressed by | |
117 | allocations > PAGE_SIZE and the number of packets in a page | |
118 | is an integer 512 is the largest possible packet on EHCI */ | |
119 | #define WRITES_IN_FLIGHT 8 | |
120 | /* arbitrarily chosen */ | |
121 | ||
2eae6bdc AS |
122 | static struct usb_driver ced_driver; |
123 | ||
124 | static void ced_delete(struct kref *kref) | |
125 | { | |
cd915200 GKH |
126 | DEVICE_EXTENSION *pdx = to_DEVICE_EXTENSION(kref); |
127 | ||
e4837704 EU |
128 | /* Free up the output buffer, then free the output urb. Note that the interface member */ |
129 | /* of pdx will probably be NULL, so cannot be used to get to dev. */ | |
cd915200 GKH |
130 | usb_free_coherent(pdx->udev, OUTBUF_SZ, pdx->pCoherCharOut, |
131 | pdx->pUrbCharOut->transfer_dma); | |
132 | usb_free_urb(pdx->pUrbCharOut); | |
133 | ||
e4837704 | 134 | /* Do the same for chan input */ |
cd915200 GKH |
135 | usb_free_coherent(pdx->udev, INBUF_SZ, pdx->pCoherCharIn, |
136 | pdx->pUrbCharIn->transfer_dma); | |
137 | usb_free_urb(pdx->pUrbCharIn); | |
138 | ||
e4837704 | 139 | /* Do the same for the block transfers */ |
cd915200 GKH |
140 | usb_free_coherent(pdx->udev, STAGED_SZ, pdx->pCoherStagedIO, |
141 | pdx->pStagedUrb->transfer_dma); | |
142 | usb_free_urb(pdx->pStagedUrb); | |
143 | ||
144 | usb_put_dev(pdx->udev); | |
145 | kfree(pdx); | |
2eae6bdc AS |
146 | } |
147 | ||
e4837704 | 148 | /* This is the driver end of the open() call from user space. */ |
2eae6bdc AS |
149 | static int ced_open(struct inode *inode, struct file *file) |
150 | { | |
cd915200 GKH |
151 | DEVICE_EXTENSION *pdx; |
152 | int retval = 0; | |
153 | int subminor = iminor(inode); | |
154 | struct usb_interface *interface = | |
155 | usb_find_interface(&ced_driver, subminor); | |
156 | if (!interface) { | |
157 | pr_err("%s - error, can't find device for minor %d", __func__, | |
158 | subminor); | |
159 | retval = -ENODEV; | |
160 | goto exit; | |
161 | } | |
162 | ||
163 | pdx = usb_get_intfdata(interface); | |
164 | if (!pdx) { | |
165 | retval = -ENODEV; | |
166 | goto exit; | |
167 | } | |
168 | ||
169 | dev_dbg(&interface->dev, "%s got pdx", __func__); | |
170 | ||
171 | /* increment our usage count for the device */ | |
172 | kref_get(&pdx->kref); | |
173 | ||
174 | /* lock the device to allow correctly handling errors | |
175 | * in resumption */ | |
176 | mutex_lock(&pdx->io_mutex); | |
177 | ||
178 | if (!pdx->open_count++) { | |
179 | retval = usb_autopm_get_interface(interface); | |
180 | if (retval) { | |
181 | pdx->open_count--; | |
182 | mutex_unlock(&pdx->io_mutex); | |
183 | kref_put(&pdx->kref, ced_delete); | |
184 | goto exit; | |
185 | } | |
e4837704 | 186 | } else { /* uncomment this block if you want exclusive open */ |
cd915200 | 187 | dev_err(&interface->dev, "%s fail: already open", __func__); |
2eae6bdc AS |
188 | retval = -EBUSY; |
189 | pdx->open_count--; | |
190 | mutex_unlock(&pdx->io_mutex); | |
191 | kref_put(&pdx->kref, ced_delete); | |
192 | goto exit; | |
193 | } | |
cd915200 | 194 | /* prevent the device from being autosuspended */ |
2eae6bdc | 195 | |
cd915200 GKH |
196 | /* save our object in the file's private structure */ |
197 | file->private_data = pdx; | |
198 | mutex_unlock(&pdx->io_mutex); | |
2eae6bdc AS |
199 | |
200 | exit: | |
cd915200 | 201 | return retval; |
2eae6bdc AS |
202 | } |
203 | ||
204 | static int ced_release(struct inode *inode, struct file *file) | |
205 | { | |
cd915200 GKH |
206 | DEVICE_EXTENSION *pdx = file->private_data; |
207 | if (pdx == NULL) | |
208 | return -ENODEV; | |
209 | ||
210 | dev_dbg(&pdx->interface->dev, "%s called", __func__); | |
211 | mutex_lock(&pdx->io_mutex); | |
e4837704 | 212 | if (!--pdx->open_count && pdx->interface) /* Allow autosuspend */ |
cd915200 GKH |
213 | usb_autopm_put_interface(pdx->interface); |
214 | mutex_unlock(&pdx->io_mutex); | |
215 | ||
e4837704 | 216 | kref_put(&pdx->kref, ced_delete); /* decrement the count on our device */ |
cd915200 | 217 | return 0; |
2eae6bdc AS |
218 | } |
219 | ||
220 | static int ced_flush(struct file *file, fl_owner_t id) | |
221 | { | |
cd915200 GKH |
222 | int res; |
223 | DEVICE_EXTENSION *pdx = file->private_data; | |
224 | if (pdx == NULL) | |
225 | return -ENODEV; | |
2eae6bdc | 226 | |
cd915200 GKH |
227 | dev_dbg(&pdx->interface->dev, "%s char in pend=%d", __func__, |
228 | pdx->bReadCharsPending); | |
2eae6bdc | 229 | |
cd915200 GKH |
230 | /* wait for io to stop */ |
231 | mutex_lock(&pdx->io_mutex); | |
232 | dev_dbg(&pdx->interface->dev, "%s got io_mutex", __func__); | |
233 | ced_draw_down(pdx); | |
2eae6bdc | 234 | |
cd915200 GKH |
235 | /* read out errors, leave subsequent opens a clean slate */ |
236 | spin_lock_irq(&pdx->err_lock); | |
237 | res = pdx->errors ? (pdx->errors == -EPIPE ? -EPIPE : -EIO) : 0; | |
238 | pdx->errors = 0; | |
239 | spin_unlock_irq(&pdx->err_lock); | |
2eae6bdc | 240 | |
cd915200 GKH |
241 | mutex_unlock(&pdx->io_mutex); |
242 | dev_dbg(&pdx->interface->dev, "%s exit reached", __func__); | |
2eae6bdc | 243 | |
cd915200 | 244 | return res; |
2eae6bdc AS |
245 | } |
246 | ||
2eae6bdc AS |
247 | /*************************************************************************** |
248 | ** CanAcceptIoRequests | |
249 | ** If the device is removed, interface is set NULL. We also clear our pointer | |
250 | ** from the interface, so we should make sure that pdx is not NULL. This will | |
251 | ** not help with a device extension held by a file. | |
252 | ** return true if can accept new io requests, else false | |
253 | */ | |
d1cc1b86 | 254 | static bool CanAcceptIoRequests(DEVICE_EXTENSION *pdx) |
2eae6bdc | 255 | { |
e4837704 | 256 | return pdx && pdx->interface; /* Can we accept IO requests */ |
2eae6bdc AS |
257 | } |
258 | ||
259 | /**************************************************************************** | |
260 | ** Callback routine to complete writes. This may need to fire off another | |
261 | ** urb to complete the transfer. | |
262 | ****************************************************************************/ | |
cd915200 | 263 | static void ced_writechar_callback(struct urb *pUrb) |
2eae6bdc | 264 | { |
cd915200 | 265 | DEVICE_EXTENSION *pdx = pUrb->context; |
e4837704 | 266 | int nGot = pUrb->actual_length; /* what we transferred */ |
cd915200 | 267 | |
e4837704 | 268 | if (pUrb->status) { /* sync/async unlink faults aren't errors */ |
cd915200 GKH |
269 | if (! |
270 | (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET | |
271 | || pUrb->status == -ESHUTDOWN)) { | |
272 | dev_err(&pdx->interface->dev, | |
273 | "%s - nonzero write bulk status received: %d", | |
274 | __func__, pUrb->status); | |
275 | } | |
276 | ||
277 | spin_lock(&pdx->err_lock); | |
278 | pdx->errors = pUrb->status; | |
279 | spin_unlock(&pdx->err_lock); | |
e4837704 | 280 | nGot = 0; /* and tidy up again if so */ |
cd915200 | 281 | |
e4837704 EU |
282 | spin_lock(&pdx->charOutLock); /* already at irq level */ |
283 | pdx->dwOutBuffGet = 0; /* Reset the output buffer */ | |
cd915200 | 284 | pdx->dwOutBuffPut = 0; |
e4837704 EU |
285 | pdx->dwNumOutput = 0; /* Clear the char count */ |
286 | pdx->bPipeError[0] = 1; /* Flag an error for later */ | |
287 | pdx->bSendCharsPending = false; /* Allow other threads again */ | |
288 | spin_unlock(&pdx->charOutLock); /* already at irq level */ | |
cd915200 GKH |
289 | dev_dbg(&pdx->interface->dev, |
290 | "%s - char out done, 0 chars sent", __func__); | |
291 | } else { | |
292 | dev_dbg(&pdx->interface->dev, | |
293 | "%s - char out done, %d chars sent", __func__, nGot); | |
e4837704 EU |
294 | spin_lock(&pdx->charOutLock); /* already at irq level */ |
295 | pdx->dwNumOutput -= nGot; /* Now adjust the char send buffer */ | |
296 | pdx->dwOutBuffGet += nGot; /* to match what we did */ | |
297 | if (pdx->dwOutBuffGet >= OUTBUF_SZ) /* Can't do this any earlier as data could be overwritten */ | |
cd915200 GKH |
298 | pdx->dwOutBuffGet = 0; |
299 | ||
e035b590 | 300 | if (pdx->dwNumOutput > 0) { /* if more to be done... */ |
e4837704 | 301 | int nPipe = 0; /* The pipe number to use */ |
cd915200 GKH |
302 | int iReturn; |
303 | char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet]; | |
e4837704 EU |
304 | unsigned int dwCount = pdx->dwNumOutput; /* maximum to send */ |
305 | if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ) /* does it cross buffer end? */ | |
cd915200 | 306 | dwCount = OUTBUF_SZ - pdx->dwOutBuffGet; |
e4837704 EU |
307 | spin_unlock(&pdx->charOutLock); /* we are done with stuff that changes */ |
308 | memcpy(pdx->pCoherCharOut, pDat, dwCount); /* copy output data to the buffer */ | |
cd915200 GKH |
309 | usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev, |
310 | usb_sndbulkpipe(pdx->udev, | |
311 | pdx->epAddr[0]), | |
312 | pdx->pCoherCharOut, dwCount, | |
313 | ced_writechar_callback, pdx); | |
314 | pdx->pUrbCharOut->transfer_flags |= | |
315 | URB_NO_TRANSFER_DMA_MAP; | |
e4837704 | 316 | usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted); /* in case we need to kill it */ |
cd915200 GKH |
317 | iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_ATOMIC); |
318 | dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__, | |
319 | dwCount, pDat); | |
e4837704 | 320 | spin_lock(&pdx->charOutLock); /* grab lock for errors */ |
cd915200 | 321 | if (iReturn) { |
e4837704 EU |
322 | pdx->bPipeError[nPipe] = 1; /* Flag an error to be handled later */ |
323 | pdx->bSendCharsPending = false; /* Allow other threads again */ | |
cd915200 GKH |
324 | usb_unanchor_urb(pdx->pUrbCharOut); |
325 | dev_err(&pdx->interface->dev, | |
326 | "%s usb_submit_urb() returned %d", | |
327 | __func__, iReturn); | |
328 | } | |
329 | } else | |
e4837704 EU |
330 | pdx->bSendCharsPending = false; /* Allow other threads again */ |
331 | spin_unlock(&pdx->charOutLock); /* already at irq level */ | |
cd915200 | 332 | } |
2eae6bdc AS |
333 | } |
334 | ||
335 | /**************************************************************************** | |
336 | ** SendChars | |
337 | ** Transmit the characters in the output buffer to the 1401. This may need | |
338 | ** breaking down into multiple transfers. | |
339 | ****************************************************************************/ | |
d1cc1b86 | 340 | int SendChars(DEVICE_EXTENSION *pdx) |
2eae6bdc | 341 | { |
cd915200 GKH |
342 | int iReturn = U14ERR_NOERROR; |
343 | ||
e4837704 | 344 | spin_lock_irq(&pdx->charOutLock); /* Protect ourselves */ |
cd915200 | 345 | |
e4837704 EU |
346 | if ((!pdx->bSendCharsPending) && /* Not currently sending */ |
347 | (pdx->dwNumOutput > 0) && /* has characters to output */ | |
e035b590 | 348 | (CanAcceptIoRequests(pdx))) { /* and current activity is OK */ |
e4837704 EU |
349 | unsigned int dwCount = pdx->dwNumOutput; /* Get a copy of the character count */ |
350 | pdx->bSendCharsPending = true; /* Set flag to lock out other threads */ | |
cd915200 GKH |
351 | |
352 | dev_dbg(&pdx->interface->dev, | |
353 | "Send %d chars to 1401, EP0 flag %d\n", dwCount, | |
354 | pdx->nPipes == 3); | |
e4837704 | 355 | /* If we have only 3 end points we must send the characters to the 1401 using EP0. */ |
cd915200 | 356 | if (pdx->nPipes == 3) { |
e4837704 EU |
357 | /* For EP0 character transmissions to the 1401, we have to hang about until they */ |
358 | /* are gone, as otherwise without more character IO activity they will never go. */ | |
359 | unsigned int count = dwCount; /* Local char counter */ | |
360 | unsigned int index = 0; /* The index into the char buffer */ | |
cd915200 | 361 | |
e4837704 | 362 | spin_unlock_irq(&pdx->charOutLock); /* Free spinlock as we call USBD */ |
cd915200 GKH |
363 | |
364 | while ((count > 0) && (iReturn == U14ERR_NOERROR)) { | |
e4837704 EU |
365 | /* We have to break the transfer up into 64-byte chunks because of a 2270 problem */ |
366 | int n = count > 64 ? 64 : count; /* Chars for this xfer, max of 64 */ | |
cd915200 | 367 | int nSent = usb_control_msg(pdx->udev, |
e4837704 EU |
368 | usb_sndctrlpipe(pdx->udev, 0), /* use end point 0 */ |
369 | DB_CHARS, /* bRequest */ | |
370 | (H_TO_D | VENDOR | DEVREQ), /* to the device, vendor request to the device */ | |
371 | 0, 0, /* value and index are both 0 */ | |
372 | &pdx->outputBuffer[index], /* where to send from */ | |
373 | n, /* how much to send */ | |
374 | 1000); /* timeout in jiffies */ | |
cd915200 | 375 | if (nSent <= 0) { |
e4837704 | 376 | iReturn = nSent ? nSent : -ETIMEDOUT; /* if 0 chars says we timed out */ |
cd915200 GKH |
377 | dev_err(&pdx->interface->dev, |
378 | "Send %d chars by EP0 failed: %d", | |
379 | n, iReturn); | |
380 | } else { | |
381 | dev_dbg(&pdx->interface->dev, | |
382 | "Sent %d chars by EP0", n); | |
383 | count -= nSent; | |
384 | index += nSent; | |
385 | } | |
386 | } | |
387 | ||
e4837704 EU |
388 | spin_lock_irq(&pdx->charOutLock); /* Protect pdx changes, released by general code */ |
389 | pdx->dwOutBuffGet = 0; /* so reset the output buffer */ | |
cd915200 | 390 | pdx->dwOutBuffPut = 0; |
e4837704 EU |
391 | pdx->dwNumOutput = 0; /* and clear the buffer count */ |
392 | pdx->bSendCharsPending = false; /* Allow other threads again */ | |
393 | } else { /* Here for sending chars normally - we hold the spin lock */ | |
394 | int nPipe = 0; /* The pipe number to use */ | |
cd915200 GKH |
395 | char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet]; |
396 | ||
e4837704 | 397 | if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ) /* does it cross buffer end? */ |
cd915200 | 398 | dwCount = OUTBUF_SZ - pdx->dwOutBuffGet; |
e4837704 EU |
399 | spin_unlock_irq(&pdx->charOutLock); /* we are done with stuff that changes */ |
400 | memcpy(pdx->pCoherCharOut, pDat, dwCount); /* copy output data to the buffer */ | |
cd915200 GKH |
401 | usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev, |
402 | usb_sndbulkpipe(pdx->udev, | |
403 | pdx->epAddr[0]), | |
404 | pdx->pCoherCharOut, dwCount, | |
405 | ced_writechar_callback, pdx); | |
406 | pdx->pUrbCharOut->transfer_flags |= | |
407 | URB_NO_TRANSFER_DMA_MAP; | |
408 | usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted); | |
409 | iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_KERNEL); | |
e4837704 | 410 | spin_lock_irq(&pdx->charOutLock); /* grab lock for errors */ |
cd915200 | 411 | if (iReturn) { |
e4837704 EU |
412 | pdx->bPipeError[nPipe] = 1; /* Flag an error to be handled later */ |
413 | pdx->bSendCharsPending = false; /* Allow other threads again */ | |
414 | usb_unanchor_urb(pdx->pUrbCharOut); /* remove from list of active urbs */ | |
cd915200 GKH |
415 | } |
416 | } | |
417 | } else if (pdx->bSendCharsPending && (pdx->dwNumOutput > 0)) | |
418 | dev_dbg(&pdx->interface->dev, | |
419 | "SendChars bSendCharsPending:true"); | |
420 | ||
421 | dev_dbg(&pdx->interface->dev, "SendChars exit code: %d", iReturn); | |
e4837704 | 422 | spin_unlock_irq(&pdx->charOutLock); /* Now let go of the spinlock */ |
cd915200 | 423 | return iReturn; |
2eae6bdc AS |
424 | } |
425 | ||
426 | /*************************************************************************** | |
427 | ** CopyUserSpace | |
428 | ** This moves memory between pinned down user space and the pCoherStagedIO | |
429 | ** memory buffer we use for transfers. Copy n bytes in the directions that | |
430 | ** is defined by pdx->StagedRead. The user space is determined by the area | |
431 | ** in pdx->StagedId and the offset in pdx->StagedDone. The user | |
432 | ** area may well not start on a page boundary, so allow for that. | |
433 | ** | |
434 | ** We have a table of physical pages that describe the area, so we can use | |
435 | ** this to get a virtual address that the kernel can use. | |
436 | ** | |
437 | ** pdx Is our device extension which holds all we know about the transfer. | |
438 | ** n The number of bytes to move one way or the other. | |
439 | ***************************************************************************/ | |
d1cc1b86 | 440 | static void CopyUserSpace(DEVICE_EXTENSION *pdx, int n) |
2eae6bdc | 441 | { |
cd915200 GKH |
442 | unsigned int nArea = pdx->StagedId; |
443 | if (nArea < MAX_TRANSAREAS) { | |
e4837704 | 444 | TRANSAREA *pArea = &pdx->rTransDef[nArea]; /* area to be used */ |
cd915200 GKH |
445 | unsigned int dwOffset = |
446 | pdx->StagedDone + pdx->StagedOffset + pArea->dwBaseOffset; | |
e4837704 | 447 | char *pCoherBuf = pdx->pCoherStagedIO; /* coherent buffer */ |
cd915200 GKH |
448 | if (!pArea->bUsed) { |
449 | dev_err(&pdx->interface->dev, "%s area %d unused", | |
450 | __func__, nArea); | |
451 | return; | |
452 | } | |
453 | ||
454 | while (n) { | |
e4837704 | 455 | int nPage = dwOffset >> PAGE_SHIFT; /* page number in table */ |
cd915200 GKH |
456 | if (nPage < pArea->nPages) { |
457 | char *pvAddress = | |
458 | (char *)kmap_atomic(pArea->pPages[nPage]); | |
459 | if (pvAddress) { | |
e4837704 EU |
460 | unsigned int uiPageOff = dwOffset & (PAGE_SIZE - 1); /* offset into the page */ |
461 | size_t uiXfer = PAGE_SIZE - uiPageOff; /* max to transfer on this page */ | |
462 | if (uiXfer > n) /* limit byte count if too much */ | |
463 | uiXfer = n; /* for the page */ | |
cd915200 GKH |
464 | if (pdx->StagedRead) |
465 | memcpy(pvAddress + uiPageOff, | |
466 | pCoherBuf, uiXfer); | |
467 | else | |
468 | memcpy(pCoherBuf, | |
469 | pvAddress + uiPageOff, | |
470 | uiXfer); | |
471 | kunmap_atomic(pvAddress); | |
472 | dwOffset += uiXfer; | |
473 | pCoherBuf += uiXfer; | |
474 | n -= uiXfer; | |
475 | } else { | |
476 | dev_err(&pdx->interface->dev, | |
477 | "%s did not map page %d", | |
478 | __func__, nPage); | |
479 | return; | |
480 | } | |
481 | ||
482 | } else { | |
483 | dev_err(&pdx->interface->dev, | |
484 | "%s exceeded pages %d", __func__, | |
485 | nPage); | |
486 | return; | |
487 | } | |
488 | } | |
489 | } else | |
490 | dev_err(&pdx->interface->dev, "%s bad area %d", __func__, | |
491 | nArea); | |
2eae6bdc AS |
492 | } |
493 | ||
e4837704 | 494 | /* Forward declarations for stuff used circularly */ |
d1cc1b86 | 495 | static int StageChunk(DEVICE_EXTENSION *pdx); |
2eae6bdc AS |
496 | /*************************************************************************** |
497 | ** ReadWrite_Complete | |
498 | ** | |
499 | ** Completion routine for our staged read/write Irps | |
500 | */ | |
cd915200 | 501 | static void staged_callback(struct urb *pUrb) |
2eae6bdc | 502 | { |
cd915200 | 503 | DEVICE_EXTENSION *pdx = pUrb->context; |
e4837704 | 504 | unsigned int nGot = pUrb->actual_length; /* what we transferred */ |
cd915200 | 505 | bool bCancel = false; |
e4837704 | 506 | bool bRestartCharInput; /* used at the end */ |
cd915200 | 507 | |
e4837704 EU |
508 | spin_lock(&pdx->stagedLock); /* stop ReadWriteMem() action while this routine is running */ |
509 | pdx->bStagedUrbPending = false; /* clear the flag for staged IRP pending */ | |
cd915200 | 510 | |
e4837704 | 511 | if (pUrb->status) { /* sync/async unlink faults aren't errors */ |
cd915200 GKH |
512 | if (! |
513 | (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET | |
514 | || pUrb->status == -ESHUTDOWN)) { | |
515 | dev_err(&pdx->interface->dev, | |
516 | "%s - nonzero write bulk status received: %d", | |
517 | __func__, pUrb->status); | |
518 | } else | |
519 | dev_info(&pdx->interface->dev, | |
520 | "%s - staged xfer cancelled", __func__); | |
521 | ||
522 | spin_lock(&pdx->err_lock); | |
523 | pdx->errors = pUrb->status; | |
524 | spin_unlock(&pdx->err_lock); | |
e4837704 | 525 | nGot = 0; /* and tidy up again if so */ |
cd915200 GKH |
526 | bCancel = true; |
527 | } else { | |
528 | dev_dbg(&pdx->interface->dev, "%s %d chars xferred", __func__, | |
529 | nGot); | |
e4837704 EU |
530 | if (pdx->StagedRead) /* if reading, save to user space */ |
531 | CopyUserSpace(pdx, nGot); /* copy from buffer to user */ | |
cd915200 GKH |
532 | if (nGot == 0) |
533 | dev_dbg(&pdx->interface->dev, "%s ZLP", __func__); | |
534 | } | |
535 | ||
e4837704 | 536 | /* Update the transfer length based on the TransferBufferLength value in the URB */ |
cd915200 GKH |
537 | pdx->StagedDone += nGot; |
538 | ||
539 | dev_dbg(&pdx->interface->dev, "%s, done %d bytes of %d", __func__, | |
540 | pdx->StagedDone, pdx->StagedLength); | |
541 | ||
e4837704 | 542 | if ((pdx->StagedDone == pdx->StagedLength) || /* If no more to do */ |
e035b590 | 543 | (bCancel)) { /* or this IRP was cancelled */ |
e4837704 | 544 | TRANSAREA *pArea = &pdx->rTransDef[pdx->StagedId]; /* Transfer area info */ |
cd915200 GKH |
545 | dev_dbg(&pdx->interface->dev, |
546 | "%s transfer done, bytes %d, cancel %d", __func__, | |
547 | pdx->StagedDone, bCancel); | |
548 | ||
e4837704 EU |
549 | /* Here is where we sort out what to do with this transfer if using a circular buffer. We have */ |
550 | /* a completed transfer that can be assumed to fit into the transfer area. We should be able to */ | |
551 | /* add this to the end of a growing block or to use it to start a new block unless the code */ | |
552 | /* that calculates the offset to use (in ReadWriteMem) is totally duff. */ | |
553 | if ((pArea->bCircular) && (pArea->bCircToHost) && (!bCancel) && /* Time to sort out circular buffer info? */ | |
e035b590 EU |
554 | (pdx->StagedRead)) { /* Only for tohost transfers for now */ |
555 | if (pArea->aBlocks[1].dwSize > 0) { /* If block 1 is in use we must append to it */ | |
cd915200 GKH |
556 | if (pdx->StagedOffset == |
557 | (pArea->aBlocks[1].dwOffset + | |
558 | pArea->aBlocks[1].dwSize)) { | |
559 | pArea->aBlocks[1].dwSize += | |
560 | pdx->StagedLength; | |
561 | dev_dbg(&pdx->interface->dev, | |
562 | "RWM_Complete, circ block 1 now %d bytes at %d", | |
563 | pArea->aBlocks[1].dwSize, | |
564 | pArea->aBlocks[1].dwOffset); | |
565 | } else { | |
e4837704 | 566 | /* Here things have gone very, very, wrong, but I cannot see how this can actually be achieved */ |
cd915200 GKH |
567 | pArea->aBlocks[1].dwOffset = |
568 | pdx->StagedOffset; | |
569 | pArea->aBlocks[1].dwSize = | |
570 | pdx->StagedLength; | |
571 | dev_err(&pdx->interface->dev, | |
572 | "%s ERROR, circ block 1 re-started %d bytes at %d", | |
573 | __func__, | |
574 | pArea->aBlocks[1].dwSize, | |
575 | pArea->aBlocks[1].dwOffset); | |
576 | } | |
e035b590 EU |
577 | } else { /* If block 1 is not used, we try to add to block 0 */ |
578 | if (pArea->aBlocks[0].dwSize > 0) { /* Got stored block 0 information? */ | |
579 | /* Must append onto the existing block 0 */ | |
cd915200 GKH |
580 | if (pdx->StagedOffset == |
581 | (pArea->aBlocks[0].dwOffset + | |
582 | pArea->aBlocks[0].dwSize)) { | |
e4837704 | 583 | pArea->aBlocks[0].dwSize += pdx->StagedLength; /* Just add this transfer in */ |
cd915200 GKH |
584 | dev_dbg(&pdx->interface->dev, |
585 | "RWM_Complete, circ block 0 now %d bytes at %d", | |
586 | pArea->aBlocks[0]. | |
587 | dwSize, | |
588 | pArea->aBlocks[0]. | |
589 | dwOffset); | |
e035b590 | 590 | } else { /* If it doesn't append, put into new block 1 */ |
cd915200 GKH |
591 | pArea->aBlocks[1].dwOffset = |
592 | pdx->StagedOffset; | |
593 | pArea->aBlocks[1].dwSize = | |
594 | pdx->StagedLength; | |
595 | dev_dbg(&pdx->interface->dev, | |
596 | "RWM_Complete, circ block 1 started %d bytes at %d", | |
597 | pArea->aBlocks[1]. | |
598 | dwSize, | |
599 | pArea->aBlocks[1]. | |
600 | dwOffset); | |
601 | } | |
e035b590 | 602 | } else { /* No info stored yet, just save in block 0 */ |
cd915200 GKH |
603 | pArea->aBlocks[0].dwOffset = |
604 | pdx->StagedOffset; | |
605 | pArea->aBlocks[0].dwSize = | |
606 | pdx->StagedLength; | |
607 | dev_dbg(&pdx->interface->dev, | |
608 | "RWM_Complete, circ block 0 started %d bytes at %d", | |
609 | pArea->aBlocks[0].dwSize, | |
610 | pArea->aBlocks[0].dwOffset); | |
611 | } | |
612 | } | |
613 | } | |
614 | ||
e035b590 | 615 | if (!bCancel) { /* Don't generate an event if cancelled */ |
cd915200 GKH |
616 | dev_dbg(&pdx->interface->dev, |
617 | "RWM_Complete, bCircular %d, bToHost %d, eStart %d, eSize %d", | |
618 | pArea->bCircular, pArea->bEventToHost, | |
619 | pArea->dwEventSt, pArea->dwEventSz); | |
e4837704 | 620 | if ((pArea->dwEventSz) && /* Set a user-mode event... */ |
e035b590 | 621 | (pdx->StagedRead == pArea->bEventToHost)) { /* ...on transfers in this direction? */ |
e4837704 EU |
622 | int iWakeUp = 0; /* assume */ |
623 | /* If we have completed the right sort of DMA transfer then set the event to notify */ | |
624 | /* the user code to wake up anyone that is waiting. */ | |
625 | if ((pArea->bCircular) && /* Circular areas use a simpler test */ | |
e035b590 EU |
626 | (pArea->bCircToHost)) { /* only in supported direction */ |
627 | /* Is total data waiting up to size limit? */ | |
cd915200 GKH |
628 | unsigned int dwTotal = |
629 | pArea->aBlocks[0].dwSize + | |
630 | pArea->aBlocks[1].dwSize; | |
631 | iWakeUp = (dwTotal >= pArea->dwEventSz); | |
632 | } else { | |
633 | unsigned int transEnd = | |
634 | pdx->StagedOffset + | |
635 | pdx->StagedLength; | |
636 | unsigned int eventEnd = | |
637 | pArea->dwEventSt + pArea->dwEventSz; | |
638 | iWakeUp = (pdx->StagedOffset < eventEnd) | |
639 | && (transEnd > pArea->dwEventSt); | |
640 | } | |
641 | ||
642 | if (iWakeUp) { | |
643 | dev_dbg(&pdx->interface->dev, | |
644 | "About to set event to notify app"); | |
e4837704 EU |
645 | wake_up_interruptible(&pArea->wqEvent); /* wake up waiting processes */ |
646 | ++pArea->iWakeUp; /* increment wakeup count */ | |
cd915200 GKH |
647 | } |
648 | } | |
649 | } | |
650 | ||
e4837704 | 651 | pdx->dwDMAFlag = MODE_CHAR; /* Switch back to char mode before ReadWriteMem call */ |
cd915200 | 652 | |
e035b590 | 653 | if (!bCancel) { /* Don't look for waiting transfer if cancelled */ |
e4837704 | 654 | /* If we have a transfer waiting, kick it off */ |
e035b590 | 655 | if (pdx->bXFerWaiting) { /* Got a block xfer waiting? */ |
cd915200 GKH |
656 | int iReturn; |
657 | dev_info(&pdx->interface->dev, | |
658 | "*** RWM_Complete *** pending transfer will now be set up!!!"); | |
659 | iReturn = | |
660 | ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard, | |
661 | pdx->rDMAInfo.wIdent, | |
662 | pdx->rDMAInfo.dwOffset, | |
663 | pdx->rDMAInfo.dwSize); | |
664 | ||
665 | if (iReturn) | |
666 | dev_err(&pdx->interface->dev, | |
667 | "RWM_Complete rw setup failed %d", | |
668 | iReturn); | |
669 | } | |
670 | } | |
671 | ||
e4837704 EU |
672 | } else /* Here for more to do */ |
673 | StageChunk(pdx); /* fire off the next bit */ | |
cd915200 | 674 | |
e4837704 EU |
675 | /* While we hold the stagedLock, see if we should reallow character input ints */ |
676 | /* Don't allow if cancelled, or if a new block has started or if there is a waiting block. */ | |
677 | /* This feels wrong as we should ask which spin lock protects dwDMAFlag. */ | |
cd915200 GKH |
678 | bRestartCharInput = !bCancel && (pdx->dwDMAFlag == MODE_CHAR) |
679 | && !pdx->bXFerWaiting; | |
680 | ||
e4837704 | 681 | spin_unlock(&pdx->stagedLock); /* Finally release the lock again */ |
cd915200 | 682 | |
e4837704 EU |
683 | /* This is not correct as dwDMAFlag is protected by the staged lock, but it is treated */ |
684 | /* in Allowi as if it were protected by the char lock. In any case, most systems will */ | |
685 | /* not be upset by char input during DMA... sigh. Needs sorting out. */ | |
686 | if (bRestartCharInput) /* may be out of date, but... */ | |
687 | Allowi(pdx); /* ...Allowi tests a lock too. */ | |
cd915200 | 688 | dev_dbg(&pdx->interface->dev, "%s done", __func__); |
2eae6bdc AS |
689 | } |
690 | ||
691 | /**************************************************************************** | |
692 | ** StageChunk | |
693 | ** | |
694 | ** Generates the next chunk of data making up a staged transfer. | |
695 | ** | |
696 | ** The calling code must have acquired the staging spinlock before calling | |
697 | ** this function, and is responsible for releasing it. We are at callback level. | |
698 | ****************************************************************************/ | |
d1cc1b86 | 699 | static int StageChunk(DEVICE_EXTENSION *pdx) |
2eae6bdc | 700 | { |
cd915200 | 701 | int iReturn = U14ERR_NOERROR; |
2eae6bdc | 702 | unsigned int ChunkSize; |
e4837704 | 703 | int nPipe = pdx->StagedRead ? 3 : 2; /* The pipe number to use for reads or writes */ |
cd915200 | 704 | if (pdx->nPipes == 3) |
e4837704 EU |
705 | nPipe--; /* Adjust for the 3-pipe case */ |
706 | if (nPipe < 0) /* and trap case that should never happen */ | |
cd915200 GKH |
707 | return U14ERR_FAIL; |
708 | ||
e035b590 | 709 | if (!CanAcceptIoRequests(pdx)) { /* got sudden remove? */ |
cd915200 GKH |
710 | dev_info(&pdx->interface->dev, "%s sudden remove, giving up", |
711 | __func__); | |
e4837704 | 712 | return U14ERR_FAIL; /* could do with a better error */ |
cd915200 GKH |
713 | } |
714 | ||
e4837704 EU |
715 | ChunkSize = (pdx->StagedLength - pdx->StagedDone); /* transfer length remaining */ |
716 | if (ChunkSize > STAGED_SZ) /* make sure to keep legal */ | |
717 | ChunkSize = STAGED_SZ; /* limit to max allowed */ | |
cd915200 | 718 | |
e4837704 EU |
719 | if (!pdx->StagedRead) /* if writing... */ |
720 | CopyUserSpace(pdx, ChunkSize); /* ...copy data into the buffer */ | |
cd915200 GKH |
721 | |
722 | usb_fill_bulk_urb(pdx->pStagedUrb, pdx->udev, | |
723 | pdx->StagedRead ? usb_rcvbulkpipe(pdx->udev, | |
724 | pdx-> | |
725 | epAddr[nPipe]) : | |
726 | usb_sndbulkpipe(pdx->udev, pdx->epAddr[nPipe]), | |
727 | pdx->pCoherStagedIO, ChunkSize, staged_callback, pdx); | |
728 | pdx->pStagedUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
e4837704 | 729 | usb_anchor_urb(pdx->pStagedUrb, &pdx->submitted); /* in case we need to kill it */ |
cd915200 GKH |
730 | iReturn = usb_submit_urb(pdx->pStagedUrb, GFP_ATOMIC); |
731 | if (iReturn) { | |
e4837704 EU |
732 | usb_unanchor_urb(pdx->pStagedUrb); /* kill it */ |
733 | pdx->bPipeError[nPipe] = 1; /* Flag an error to be handled later */ | |
cd915200 GKH |
734 | dev_err(&pdx->interface->dev, "%s submit urb failed, code %d", |
735 | __func__, iReturn); | |
736 | } else | |
e4837704 | 737 | pdx->bStagedUrbPending = true; /* Set the flag for staged URB pending */ |
cd915200 GKH |
738 | dev_dbg(&pdx->interface->dev, "%s done so far:%d, this size:%d", |
739 | __func__, pdx->StagedDone, ChunkSize); | |
740 | ||
741 | return iReturn; | |
2eae6bdc AS |
742 | } |
743 | ||
744 | /*************************************************************************** | |
745 | ** ReadWriteMem | |
746 | ** | |
747 | ** This routine is used generally for block read and write operations. | |
748 | ** Breaks up a read or write in to specified sized chunks, as specified by pipe | |
749 | ** information on maximum transfer size. | |
750 | ** | |
751 | ** Any code that calls this must be holding the stagedLock | |
752 | ** | |
753 | ** Arguments: | |
754 | ** DeviceObject - pointer to our FDO (Functional Device Object) | |
755 | ** Read - TRUE for read, FALSE for write. This is from POV of the driver | |
756 | ** wIdent - the transfer area number - defines memory area and more. | |
757 | ** dwOffs - the start offset within the transfer area of the start of this | |
758 | ** transfer. | |
759 | ** dwLen - the number of bytes to transfer. | |
760 | */ | |
d1cc1b86 | 761 | int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent, |
cd915200 | 762 | unsigned int dwOffs, unsigned int dwLen) |
2eae6bdc | 763 | { |
e4837704 | 764 | TRANSAREA *pArea = &pdx->rTransDef[wIdent]; /* Transfer area info */ |
cd915200 | 765 | |
e035b590 | 766 | if (!CanAcceptIoRequests(pdx)) { /* Are we in a state to accept new requests? */ |
cd915200 GKH |
767 | dev_err(&pdx->interface->dev, "%s can't accept requests", |
768 | __func__); | |
769 | return U14ERR_FAIL; | |
770 | } | |
771 | ||
772 | dev_dbg(&pdx->interface->dev, | |
773 | "%s xfer %d bytes to %s, offset %d, area %d", __func__, dwLen, | |
774 | Read ? "host" : "1401", dwOffs, wIdent); | |
775 | ||
e4837704 EU |
776 | /* Amazingly, we can get an escape sequence back before the current staged Urb is done, so we */ |
777 | /* have to check for this situation and, if so, wait until all is OK. */ | |
cd915200 | 778 | if (pdx->bStagedUrbPending) { |
e4837704 | 779 | pdx->bXFerWaiting = true; /* Flag we are waiting */ |
cd915200 GKH |
780 | dev_info(&pdx->interface->dev, |
781 | "%s xfer is waiting, as previous staged pending", | |
782 | __func__); | |
783 | return U14ERR_NOERROR; | |
784 | } | |
785 | ||
e035b590 | 786 | if (dwLen == 0) { /* allow 0-len read or write; just return success */ |
cd915200 GKH |
787 | dev_dbg(&pdx->interface->dev, |
788 | "%s OK; zero-len read/write request", __func__); | |
789 | return U14ERR_NOERROR; | |
790 | } | |
791 | ||
e4837704 | 792 | if ((pArea->bCircular) && /* Circular transfer? */ |
e035b590 EU |
793 | (pArea->bCircToHost) && (Read)) { /* In a supported direction */ |
794 | /* If so, we sort out offset ourself */ | |
e4837704 | 795 | bool bWait = false; /* Flag for transfer having to wait */ |
cd915200 GKH |
796 | |
797 | dev_dbg(&pdx->interface->dev, | |
798 | "Circular buffers are %d at %d and %d at %d", | |
799 | pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset, | |
800 | pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset); | |
e035b590 | 801 | if (pArea->aBlocks[1].dwSize > 0) { /* Using the second block already? */ |
e4837704 EU |
802 | dwOffs = pArea->aBlocks[1].dwOffset + pArea->aBlocks[1].dwSize; /* take offset from that */ |
803 | bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; /* Wait if will overwrite block 0? */ | |
804 | bWait |= (dwOffs + dwLen) > pArea->dwLength; /* or if it overflows the buffer */ | |
e035b590 | 805 | } else { /* Area 1 not in use, try to use area 0 */ |
e4837704 | 806 | if (pArea->aBlocks[0].dwSize == 0) /* Reset block 0 if not in use */ |
cd915200 GKH |
807 | pArea->aBlocks[0].dwOffset = 0; |
808 | dwOffs = | |
809 | pArea->aBlocks[0].dwOffset + | |
810 | pArea->aBlocks[0].dwSize; | |
e035b590 | 811 | if ((dwOffs + dwLen) > pArea->dwLength) { /* Off the end of the buffer? */ |
e4837704 | 812 | pArea->aBlocks[1].dwOffset = 0; /* Set up to use second block */ |
cd915200 | 813 | dwOffs = 0; |
e4837704 EU |
814 | bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; /* Wait if will overwrite block 0? */ |
815 | bWait |= (dwOffs + dwLen) > pArea->dwLength; /* or if it overflows the buffer */ | |
cd915200 GKH |
816 | } |
817 | } | |
818 | ||
e035b590 | 819 | if (bWait) { /* This transfer will have to wait? */ |
e4837704 | 820 | pdx->bXFerWaiting = true; /* Flag we are waiting */ |
cd915200 GKH |
821 | dev_dbg(&pdx->interface->dev, |
822 | "%s xfer waiting for circular buffer space", | |
823 | __func__); | |
824 | return U14ERR_NOERROR; | |
825 | } | |
826 | ||
827 | dev_dbg(&pdx->interface->dev, | |
828 | "%s circular xfer, %d bytes starting at %d", __func__, | |
829 | dwLen, dwOffs); | |
830 | } | |
e4837704 EU |
831 | /* Save the parameters for the read\write transfer */ |
832 | pdx->StagedRead = Read; /* Save the parameters for this read */ | |
833 | pdx->StagedId = wIdent; /* ID allows us to get transfer area info */ | |
834 | pdx->StagedOffset = dwOffs; /* The area within the transfer area */ | |
cd915200 | 835 | pdx->StagedLength = dwLen; |
e4837704 EU |
836 | pdx->StagedDone = 0; /* Initialise the byte count */ |
837 | pdx->dwDMAFlag = MODE_LINEAR; /* Set DMA mode flag at this point */ | |
838 | pdx->bXFerWaiting = false; /* Clearly not a transfer waiting now */ | |
2eae6bdc | 839 | |
e4837704 EU |
840 | /* KeClearEvent(&pdx->StagingDoneEvent); // Clear the transfer done event */ |
841 | StageChunk(pdx); /* fire off the first chunk */ | |
2eae6bdc | 842 | |
cd915200 | 843 | return U14ERR_NOERROR; |
2eae6bdc AS |
844 | } |
845 | ||
846 | /**************************************************************************** | |
847 | ** | |
848 | ** ReadChar | |
849 | ** | |
850 | ** Reads a character a buffer. If there is no more | |
851 | ** data we return FALSE. Used as part of decoding a DMA request. | |
852 | ** | |
853 | ****************************************************************************/ | |
cd915200 GKH |
854 | static bool ReadChar(unsigned char *pChar, char *pBuf, unsigned int *pdDone, |
855 | unsigned int dGot) | |
2eae6bdc | 856 | { |
cd915200 GKH |
857 | bool bRead = false; |
858 | unsigned int dDone = *pdDone; | |
859 | ||
e035b590 | 860 | if (dDone < dGot) { /* If there is more data */ |
e4837704 EU |
861 | *pChar = (unsigned char)pBuf[dDone]; /* Extract the next char */ |
862 | dDone++; /* Increment the done count */ | |
cd915200 | 863 | *pdDone = dDone; |
e4837704 | 864 | bRead = true; /* and flag success */ |
cd915200 GKH |
865 | } |
866 | ||
867 | return bRead; | |
2eae6bdc AS |
868 | } |
869 | ||
870 | #ifdef NOTUSED | |
871 | /**************************************************************************** | |
872 | ** | |
873 | ** ReadWord | |
874 | ** | |
875 | ** Reads a word from the 1401, just uses ReadChar twice; passes on any error | |
876 | ** | |
877 | *****************************************************************************/ | |
cd915200 GKH |
878 | static bool ReadWord(unsigned short *pWord, char *pBuf, unsigned int *pdDone, |
879 | unsigned int dGot) | |
2eae6bdc | 880 | { |
cd915200 GKH |
881 | if (ReadChar((unsigned char *)pWord, pBuf, pdDone, dGot)) |
882 | return ReadChar(((unsigned char *)pWord) + 1, pBuf, pdDone, | |
883 | dGot); | |
884 | else | |
885 | return false; | |
2eae6bdc AS |
886 | } |
887 | #endif | |
888 | ||
889 | /**************************************************************************** | |
890 | ** ReadHuff | |
891 | ** | |
892 | ** Reads a coded number in and returns it, Code is: | |
b1a21ee9 MI |
893 | ** If data is in range 0..127 we receive 1 byte. If data in range 128-16383 |
894 | ** we receive two bytes, top bit of first indicates another on its way. If | |
895 | ** data in range 16384-4194303 we get three bytes, top two bits of first set | |
2eae6bdc AS |
896 | ** to indicate three byte total. |
897 | ** | |
898 | *****************************************************************************/ | |
cd915200 GKH |
899 | static bool ReadHuff(volatile unsigned int *pDWord, char *pBuf, |
900 | unsigned int *pdDone, unsigned int dGot) | |
2eae6bdc | 901 | { |
cd915200 GKH |
902 | unsigned char ucData; /* for each read to ReadChar */ |
903 | bool bReturn = true; /* assume we will succeed */ | |
904 | unsigned int dwData = 0; /* Accumulator for the data */ | |
905 | ||
906 | if (ReadChar(&ucData, pBuf, pdDone, dGot)) { | |
907 | dwData = ucData; /* copy the data */ | |
908 | if ((dwData & 0x00000080) != 0) { /* Bit set for more data ? */ | |
909 | dwData &= 0x0000007F; /* Clear the relevant bit */ | |
910 | if (ReadChar(&ucData, pBuf, pdDone, dGot)) { | |
911 | dwData = (dwData << 8) | ucData; | |
912 | if ((dwData & 0x00004000) != 0) { /* three byte sequence ? */ | |
913 | dwData &= 0x00003FFF; /* Clear the relevant bit */ | |
914 | if (ReadChar | |
915 | (&ucData, pBuf, pdDone, dGot)) | |
916 | dwData = (dwData << 8) | ucData; | |
917 | else | |
918 | bReturn = false; | |
919 | } | |
920 | } else | |
921 | bReturn = false; /* couldn't read data */ | |
922 | } | |
923 | } else | |
924 | bReturn = false; | |
925 | ||
926 | *pDWord = dwData; /* return the data */ | |
927 | return bReturn; | |
2eae6bdc AS |
928 | } |
929 | ||
930 | /*************************************************************************** | |
931 | ** | |
932 | ** ReadDMAInfo | |
933 | ** | |
934 | ** Tries to read info about the dma request from the 1401 and decode it into | |
935 | ** the dma descriptor block. We have at this point had the escape character | |
936 | ** from the 1401 and now we must read in the rest of the information about | |
937 | ** the transfer request. Returns FALSE if 1401 fails to respond or obselete | |
938 | ** code from 1401 or bad parameters. | |
939 | ** | |
940 | ** The pBuf char pointer does not include the initial escape character, so | |
941 | ** we start handling the data at offset zero. | |
942 | ** | |
943 | *****************************************************************************/ | |
d1cc1b86 | 944 | static bool ReadDMAInfo(volatile DMADESC *pDmaDesc, DEVICE_EXTENSION *pdx, |
cd915200 | 945 | char *pBuf, unsigned int dwCount) |
2eae6bdc | 946 | { |
e4837704 | 947 | bool bResult = false; /* assume we won't succeed */ |
cd915200 | 948 | unsigned char ucData; |
e4837704 | 949 | unsigned int dDone = 0; /* We haven't parsed anything so far */ |
cd915200 GKH |
950 | |
951 | dev_dbg(&pdx->interface->dev, "%s", __func__); | |
952 | ||
953 | if (ReadChar(&ucData, pBuf, &dDone, dwCount)) { | |
e4837704 EU |
954 | unsigned char ucTransCode = (ucData & 0x0F); /* get code for transfer type */ |
955 | unsigned short wIdent = ((ucData >> 4) & 0x07); /* and area identifier */ | |
cd915200 | 956 | |
e4837704 EU |
957 | /* fill in the structure we were given */ |
958 | pDmaDesc->wTransType = ucTransCode; /* type of transfer */ | |
959 | pDmaDesc->wIdent = wIdent; /* area to use */ | |
960 | pDmaDesc->dwSize = 0; /* initialise other bits */ | |
cd915200 GKH |
961 | pDmaDesc->dwOffset = 0; |
962 | ||
963 | dev_dbg(&pdx->interface->dev, "%s type: %d ident: %d", __func__, | |
964 | pDmaDesc->wTransType, pDmaDesc->wIdent); | |
965 | ||
e4837704 | 966 | pDmaDesc->bOutWard = (ucTransCode != TM_EXTTOHOST); /* set transfer direction */ |
cd915200 GKH |
967 | |
968 | switch (ucTransCode) { | |
e4837704 | 969 | case TM_EXTTOHOST: /* Extended linear transfer modes (the only ones!) */ |
cd915200 GKH |
970 | case TM_EXTTO1401: |
971 | { | |
972 | bResult = | |
973 | ReadHuff(&(pDmaDesc->dwOffset), pBuf, | |
974 | &dDone, dwCount) | |
975 | && ReadHuff(&(pDmaDesc->dwSize), pBuf, | |
976 | &dDone, dwCount); | |
977 | if (bResult) { | |
978 | dev_dbg(&pdx->interface->dev, | |
979 | "%s xfer offset & size %d %d", | |
980 | __func__, pDmaDesc->dwOffset, | |
981 | pDmaDesc->dwSize); | |
982 | ||
e4837704 EU |
983 | if ((wIdent >= MAX_TRANSAREAS) || /* Illegal area number, or... */ |
984 | (!pdx->rTransDef[wIdent].bUsed) || /* area not set up, or... */ | |
985 | (pDmaDesc->dwOffset > pdx->rTransDef[wIdent].dwLength) || /* range/size */ | |
cd915200 GKH |
986 | ((pDmaDesc->dwOffset + |
987 | pDmaDesc->dwSize) > | |
988 | (pdx->rTransDef[wIdent]. | |
989 | dwLength))) { | |
e4837704 | 990 | bResult = false; /* bad parameter(s) */ |
cd915200 GKH |
991 | dev_dbg(&pdx->interface->dev, |
992 | "%s bad param - id %d, bUsed %d, offset %d, size %d, area length %d", | |
993 | __func__, wIdent, | |
994 | pdx->rTransDef[wIdent]. | |
995 | bUsed, | |
996 | pDmaDesc->dwOffset, | |
997 | pDmaDesc->dwSize, | |
998 | pdx->rTransDef[wIdent]. | |
999 | dwLength); | |
1000 | } | |
1001 | } | |
1002 | break; | |
1003 | } | |
1004 | default: | |
1005 | break; | |
1006 | } | |
1007 | } else | |
1008 | bResult = false; | |
1009 | ||
e4837704 | 1010 | if (!bResult) /* now check parameters for validity */ |
cd915200 GKH |
1011 | dev_err(&pdx->interface->dev, "%s error reading Esc sequence", |
1012 | __func__); | |
1013 | ||
1014 | return bResult; | |
2eae6bdc AS |
1015 | } |
1016 | ||
1017 | /**************************************************************************** | |
1018 | ** | |
1019 | ** Handle1401Esc | |
1020 | ** | |
1021 | ** Deals with an escape sequence coming from the 1401. This can either be | |
1022 | ** a DMA transfer request of various types or a response to an escape sequence | |
1023 | ** sent to the 1401. This is called from a callback. | |
1024 | ** | |
1025 | ** Parameters are | |
1026 | ** | |
1027 | ** dwCount - the number of characters in the device extension char in buffer, | |
1028 | ** this is known to be at least 2 or we will not be called. | |
1029 | ** | |
1030 | ****************************************************************************/ | |
d1cc1b86 | 1031 | static int Handle1401Esc(DEVICE_EXTENSION *pdx, char *pCh, |
cd915200 | 1032 | unsigned int dwCount) |
2eae6bdc | 1033 | { |
cd915200 GKH |
1034 | int iReturn = U14ERR_FAIL; |
1035 | ||
e4837704 EU |
1036 | /* I have no idea what this next test is about. '?' is 0x3f, which is area 3, code */ |
1037 | /* 15. At the moment, this is not used, so it does no harm, but unless someone can */ | |
1038 | /* tell me what this is for, it should be removed from this and the Windows driver. */ | |
e035b590 EU |
1039 | if (pCh[0] == '?') { /* Is this an information response */ |
1040 | /* Parse and save the information */ | |
cd915200 | 1041 | } else { |
e4837704 | 1042 | spin_lock(&pdx->stagedLock); /* Lock others out */ |
cd915200 | 1043 | |
e035b590 | 1044 | if (ReadDMAInfo(&pdx->rDMAInfo, pdx, pCh, dwCount)) { /* Get DMA parameters */ |
e4837704 | 1045 | unsigned short wTransType = pdx->rDMAInfo.wTransType; /* check transfer type */ |
cd915200 GKH |
1046 | |
1047 | dev_dbg(&pdx->interface->dev, | |
1048 | "%s xfer to %s, offset %d, length %d", __func__, | |
1049 | pdx->rDMAInfo.bOutWard ? "1401" : "host", | |
1050 | pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize); | |
1051 | ||
e035b590 EU |
1052 | if (pdx->bXFerWaiting) { /* Check here for badly out of kilter... */ |
1053 | /* This can never happen, really */ | |
cd915200 GKH |
1054 | dev_err(&pdx->interface->dev, |
1055 | "ERROR: DMA setup while transfer still waiting"); | |
95d8ee54 | 1056 | spin_unlock(&pdx->stagedLock); |
cd915200 GKH |
1057 | } else { |
1058 | if ((wTransType == TM_EXTTOHOST) | |
1059 | || (wTransType == TM_EXTTO1401)) { | |
1060 | iReturn = | |
1061 | ReadWriteMem(pdx, | |
1062 | !pdx->rDMAInfo. | |
1063 | bOutWard, | |
1064 | pdx->rDMAInfo.wIdent, | |
1065 | pdx->rDMAInfo.dwOffset, | |
1066 | pdx->rDMAInfo.dwSize); | |
1067 | if (iReturn != U14ERR_NOERROR) | |
1068 | dev_err(&pdx->interface->dev, | |
1069 | "%s ReadWriteMem() failed %d", | |
1070 | __func__, iReturn); | |
e4837704 | 1071 | } else /* This covers non-linear transfer setup */ |
cd915200 GKH |
1072 | dev_err(&pdx->interface->dev, |
1073 | "%s Unknown block xfer type %d", | |
1074 | __func__, wTransType); | |
1075 | } | |
e4837704 | 1076 | } else /* Failed to read parameters */ |
cd915200 GKH |
1077 | dev_err(&pdx->interface->dev, "%s ReadDMAInfo() fail", |
1078 | __func__); | |
1079 | ||
e4837704 | 1080 | spin_unlock(&pdx->stagedLock); /* OK here */ |
cd915200 GKH |
1081 | } |
1082 | ||
1083 | dev_dbg(&pdx->interface->dev, "%s returns %d", __func__, iReturn); | |
1084 | ||
1085 | return iReturn; | |
2eae6bdc AS |
1086 | } |
1087 | ||
1088 | /**************************************************************************** | |
1089 | ** Callback for the character read complete or error | |
1090 | ****************************************************************************/ | |
cd915200 | 1091 | static void ced_readchar_callback(struct urb *pUrb) |
2eae6bdc | 1092 | { |
cd915200 | 1093 | DEVICE_EXTENSION *pdx = pUrb->context; |
e4837704 | 1094 | int nGot = pUrb->actual_length; /* what we transferred */ |
cd915200 | 1095 | |
e035b590 | 1096 | if (pUrb->status) { /* Do we have a problem to handle? */ |
e4837704 EU |
1097 | int nPipe = pdx->nPipes == 4 ? 1 : 0; /* The pipe number to use for error */ |
1098 | /* sync/async unlink faults aren't errors... just saying device removed or stopped */ | |
cd915200 GKH |
1099 | if (! |
1100 | (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET | |
1101 | || pUrb->status == -ESHUTDOWN)) { | |
1102 | dev_err(&pdx->interface->dev, | |
1103 | "%s - nonzero write bulk status received: %d", | |
1104 | __func__, pUrb->status); | |
1105 | } else | |
1106 | dev_dbg(&pdx->interface->dev, | |
1107 | "%s - 0 chars pUrb->status=%d (shutdown?)", | |
1108 | __func__, pUrb->status); | |
1109 | ||
1110 | spin_lock(&pdx->err_lock); | |
1111 | pdx->errors = pUrb->status; | |
1112 | spin_unlock(&pdx->err_lock); | |
e4837704 | 1113 | nGot = 0; /* and tidy up again if so */ |
cd915200 | 1114 | |
e4837704 EU |
1115 | spin_lock(&pdx->charInLock); /* already at irq level */ |
1116 | pdx->bPipeError[nPipe] = 1; /* Flag an error for later */ | |
cd915200 | 1117 | } else { |
e035b590 | 1118 | if ((nGot > 1) && ((pdx->pCoherCharIn[0] & 0x7f) == 0x1b)) { /* Esc sequence? */ |
e4837704 EU |
1119 | Handle1401Esc(pdx, &pdx->pCoherCharIn[1], nGot - 1); /* handle it */ |
1120 | spin_lock(&pdx->charInLock); /* already at irq level */ | |
cd915200 | 1121 | } else { |
e4837704 | 1122 | spin_lock(&pdx->charInLock); /* already at irq level */ |
cd915200 GKH |
1123 | if (nGot > 0) { |
1124 | unsigned int i; | |
1125 | if (nGot < INBUF_SZ) { | |
e4837704 | 1126 | pdx->pCoherCharIn[nGot] = 0; /* tidy the string */ |
cd915200 GKH |
1127 | dev_dbg(&pdx->interface->dev, |
1128 | "%s got %d chars >%s<", | |
1129 | __func__, nGot, | |
1130 | pdx->pCoherCharIn); | |
1131 | } | |
e4837704 | 1132 | /* We know that whatever we read must fit in the input buffer */ |
cd915200 GKH |
1133 | for (i = 0; i < nGot; i++) { |
1134 | pdx->inputBuffer[pdx->dwInBuffPut++] = | |
1135 | pdx->pCoherCharIn[i] & 0x7F; | |
1136 | if (pdx->dwInBuffPut >= INBUF_SZ) | |
1137 | pdx->dwInBuffPut = 0; | |
1138 | } | |
1139 | ||
1140 | if ((pdx->dwNumInput + nGot) <= INBUF_SZ) | |
e4837704 | 1141 | pdx->dwNumInput += nGot; /* Adjust the buffer count accordingly */ |
cd915200 GKH |
1142 | } else |
1143 | dev_dbg(&pdx->interface->dev, "%s read ZLP", | |
1144 | __func__); | |
1145 | } | |
1146 | } | |
1147 | ||
e4837704 EU |
1148 | pdx->bReadCharsPending = false; /* No longer have a pending read */ |
1149 | spin_unlock(&pdx->charInLock); /* already at irq level */ | |
cd915200 | 1150 | |
e4837704 | 1151 | Allowi(pdx); /* see if we can do the next one */ |
2eae6bdc AS |
1152 | } |
1153 | ||
1154 | /**************************************************************************** | |
1155 | ** Allowi | |
1156 | ** | |
1157 | ** This is used to make sure that there is always a pending input transfer so | |
1158 | ** we can pick up any inward transfers. This can be called in multiple contexts | |
1159 | ** so we use the irqsave version of the spinlock. | |
1160 | ****************************************************************************/ | |
d1cc1b86 | 1161 | int Allowi(DEVICE_EXTENSION *pdx) |
2eae6bdc | 1162 | { |
cd915200 GKH |
1163 | int iReturn = U14ERR_NOERROR; |
1164 | unsigned long flags; | |
e4837704 EU |
1165 | spin_lock_irqsave(&pdx->charInLock, flags); /* can be called in multiple contexts */ |
1166 | ||
1167 | /* We don't want char input running while DMA is in progress as we know that this */ | |
1168 | /* can cause sequencing problems for the 2270. So don't. It will also allow the */ | |
1169 | /* ERR response to get back to the host code too early on some PCs, even if there */ | |
1170 | /* is no actual driver failure, so we don't allow this at all. */ | |
1171 | if (!pdx->bInDrawDown && /* stop input if */ | |
1172 | !pdx->bReadCharsPending && /* If no read request outstanding */ | |
1173 | (pdx->dwNumInput < (INBUF_SZ / 2)) && /* and there is some space */ | |
1174 | (pdx->dwDMAFlag == MODE_CHAR) && /* not doing any DMA */ | |
1175 | (!pdx->bXFerWaiting) && /* no xfer waiting to start */ | |
e035b590 EU |
1176 | (CanAcceptIoRequests(pdx))) { /* and activity is generally OK */ |
1177 | /* then off we go */ | |
e4837704 EU |
1178 | unsigned int nMax = INBUF_SZ - pdx->dwNumInput; /* max we could read */ |
1179 | int nPipe = pdx->nPipes == 4 ? 1 : 0; /* The pipe number to use */ | |
cd915200 GKH |
1180 | |
1181 | dev_dbg(&pdx->interface->dev, "%s %d chars in input buffer", | |
1182 | __func__, pdx->dwNumInput); | |
1183 | ||
1184 | usb_fill_int_urb(pdx->pUrbCharIn, pdx->udev, | |
1185 | usb_rcvintpipe(pdx->udev, pdx->epAddr[nPipe]), | |
1186 | pdx->pCoherCharIn, nMax, ced_readchar_callback, | |
1187 | pdx, pdx->bInterval); | |
e4837704 EU |
1188 | pdx->pUrbCharIn->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* short xfers are OK by default */ |
1189 | usb_anchor_urb(pdx->pUrbCharIn, &pdx->submitted); /* in case we need to kill it */ | |
955e7da8 | 1190 | iReturn = usb_submit_urb(pdx->pUrbCharIn, GFP_ATOMIC); |
cd915200 | 1191 | if (iReturn) { |
e4837704 EU |
1192 | usb_unanchor_urb(pdx->pUrbCharIn); /* remove from list of active Urbs */ |
1193 | pdx->bPipeError[nPipe] = 1; /* Flag an error to be handled later */ | |
cd915200 GKH |
1194 | dev_err(&pdx->interface->dev, |
1195 | "%s submit urb failed: %d", __func__, iReturn); | |
1196 | } else | |
e4837704 | 1197 | pdx->bReadCharsPending = true; /* Flag that we are active here */ |
cd915200 GKH |
1198 | } |
1199 | ||
1200 | spin_unlock_irqrestore(&pdx->charInLock, flags); | |
1201 | ||
1202 | return iReturn; | |
2eae6bdc AS |
1203 | |
1204 | } | |
1205 | ||
1206 | /***************************************************************************** | |
1207 | ** The ioctl entry point to the driver that is used by us to talk to it. | |
1208 | ** inode The device node (no longer in 3.0.0 kernels) | |
1209 | ** file The file that is open, which holds our pdx pointer | |
1210 | ** ulArg The argument passed in. Note that long is 64-bits in 64-bit system, i.e. it is big | |
1211 | ** enough for a 64-bit pointer. | |
1212 | *****************************************************************************/ | |
cd915200 | 1213 | static long ced_ioctl(struct file *file, unsigned int cmd, unsigned long ulArg) |
2eae6bdc | 1214 | { |
cd915200 GKH |
1215 | int err = 0; |
1216 | DEVICE_EXTENSION *pdx = file->private_data; | |
e4837704 | 1217 | if (!CanAcceptIoRequests(pdx)) /* check we still exist */ |
cd915200 | 1218 | return -ENODEV; |
2eae6bdc | 1219 | |
e4837704 EU |
1220 | /* Check that access is allowed, where is is needed. Anything that would have an indeterminate */ |
1221 | /* size will be checked by the specific command. */ | |
1222 | if (_IOC_DIR(cmd) & _IOC_READ) /* read from point of view of user... */ | |
1223 | err = !access_ok(VERIFY_WRITE, (void __user *)ulArg, _IOC_SIZE(cmd)); /* is kernel write */ | |
1224 | else if (_IOC_DIR(cmd) & _IOC_WRITE) /* and write from point of view of user... */ | |
1225 | err = !access_ok(VERIFY_READ, (void __user *)ulArg, _IOC_SIZE(cmd)); /* is kernel read */ | |
cd915200 GKH |
1226 | if (err) |
1227 | return -EFAULT; | |
2eae6bdc | 1228 | |
cd915200 GKH |
1229 | switch (_IOC_NR(cmd)) { |
1230 | case _IOC_NR(IOCTL_CED_SENDSTRING(0)): | |
1231 | return SendString(pdx, (const char __user *)ulArg, | |
1232 | _IOC_SIZE(cmd)); | |
2eae6bdc | 1233 | |
cd915200 GKH |
1234 | case _IOC_NR(IOCTL_CED_RESET1401): |
1235 | return Reset1401(pdx); | |
2eae6bdc | 1236 | |
cd915200 GKH |
1237 | case _IOC_NR(IOCTL_CED_GETCHAR): |
1238 | return GetChar(pdx); | |
2eae6bdc | 1239 | |
cd915200 GKH |
1240 | case _IOC_NR(IOCTL_CED_SENDCHAR): |
1241 | return SendChar(pdx, (char)ulArg); | |
2eae6bdc | 1242 | |
cd915200 GKH |
1243 | case _IOC_NR(IOCTL_CED_STAT1401): |
1244 | return Stat1401(pdx); | |
2eae6bdc | 1245 | |
cd915200 GKH |
1246 | case _IOC_NR(IOCTL_CED_LINECOUNT): |
1247 | return LineCount(pdx); | |
2eae6bdc | 1248 | |
cd915200 GKH |
1249 | case _IOC_NR(IOCTL_CED_GETSTRING(0)): |
1250 | return GetString(pdx, (char __user *)ulArg, _IOC_SIZE(cmd)); | |
2eae6bdc | 1251 | |
cd915200 GKH |
1252 | case _IOC_NR(IOCTL_CED_SETTRANSFER): |
1253 | return SetTransfer(pdx, (TRANSFERDESC __user *) ulArg); | |
2eae6bdc | 1254 | |
cd915200 GKH |
1255 | case _IOC_NR(IOCTL_CED_UNSETTRANSFER): |
1256 | return UnsetTransfer(pdx, (int)ulArg); | |
2eae6bdc | 1257 | |
cd915200 GKH |
1258 | case _IOC_NR(IOCTL_CED_SETEVENT): |
1259 | return SetEvent(pdx, (TRANSFEREVENT __user *) ulArg); | |
2eae6bdc | 1260 | |
cd915200 GKH |
1261 | case _IOC_NR(IOCTL_CED_GETOUTBUFSPACE): |
1262 | return GetOutBufSpace(pdx); | |
2eae6bdc | 1263 | |
cd915200 GKH |
1264 | case _IOC_NR(IOCTL_CED_GETBASEADDRESS): |
1265 | return -1; | |
2eae6bdc | 1266 | |
cd915200 | 1267 | case _IOC_NR(IOCTL_CED_GETDRIVERREVISION): |
e4837704 | 1268 | return (2 << 24) | (DRIVERMAJREV << 16) | DRIVERMINREV; /* USB | MAJOR | MINOR */ |
2eae6bdc | 1269 | |
cd915200 GKH |
1270 | case _IOC_NR(IOCTL_CED_GETTRANSFER): |
1271 | return GetTransfer(pdx, (TGET_TX_BLOCK __user *) ulArg); | |
2eae6bdc | 1272 | |
cd915200 GKH |
1273 | case _IOC_NR(IOCTL_CED_KILLIO1401): |
1274 | return KillIO1401(pdx); | |
2eae6bdc | 1275 | |
cd915200 GKH |
1276 | case _IOC_NR(IOCTL_CED_STATEOF1401): |
1277 | return StateOf1401(pdx); | |
2eae6bdc | 1278 | |
cd915200 GKH |
1279 | case _IOC_NR(IOCTL_CED_GRAB1401): |
1280 | case _IOC_NR(IOCTL_CED_FREE1401): | |
1281 | return U14ERR_NOERROR; | |
2eae6bdc | 1282 | |
cd915200 GKH |
1283 | case _IOC_NR(IOCTL_CED_STARTSELFTEST): |
1284 | return StartSelfTest(pdx); | |
2eae6bdc | 1285 | |
cd915200 GKH |
1286 | case _IOC_NR(IOCTL_CED_CHECKSELFTEST): |
1287 | return CheckSelfTest(pdx, (TGET_SELFTEST __user *) ulArg); | |
2eae6bdc | 1288 | |
cd915200 GKH |
1289 | case _IOC_NR(IOCTL_CED_TYPEOF1401): |
1290 | return TypeOf1401(pdx); | |
2eae6bdc | 1291 | |
cd915200 GKH |
1292 | case _IOC_NR(IOCTL_CED_TRANSFERFLAGS): |
1293 | return TransferFlags(pdx); | |
2eae6bdc | 1294 | |
cd915200 GKH |
1295 | case _IOC_NR(IOCTL_CED_DBGPEEK): |
1296 | return DbgPeek(pdx, (TDBGBLOCK __user *) ulArg); | |
2eae6bdc | 1297 | |
cd915200 GKH |
1298 | case _IOC_NR(IOCTL_CED_DBGPOKE): |
1299 | return DbgPoke(pdx, (TDBGBLOCK __user *) ulArg); | |
2eae6bdc | 1300 | |
cd915200 GKH |
1301 | case _IOC_NR(IOCTL_CED_DBGRAMPDATA): |
1302 | return DbgRampData(pdx, (TDBGBLOCK __user *) ulArg); | |
2eae6bdc | 1303 | |
cd915200 GKH |
1304 | case _IOC_NR(IOCTL_CED_DBGRAMPADDR): |
1305 | return DbgRampAddr(pdx, (TDBGBLOCK __user *) ulArg); | |
2eae6bdc | 1306 | |
cd915200 GKH |
1307 | case _IOC_NR(IOCTL_CED_DBGGETDATA): |
1308 | return DbgGetData(pdx, (TDBGBLOCK __user *) ulArg); | |
2eae6bdc | 1309 | |
cd915200 GKH |
1310 | case _IOC_NR(IOCTL_CED_DBGSTOPLOOP): |
1311 | return DbgStopLoop(pdx); | |
2eae6bdc | 1312 | |
cd915200 | 1313 | case _IOC_NR(IOCTL_CED_FULLRESET): |
e4837704 | 1314 | pdx->bForceReset = true; /* Set a flag for a full reset */ |
cd915200 | 1315 | break; |
2eae6bdc | 1316 | |
cd915200 GKH |
1317 | case _IOC_NR(IOCTL_CED_SETCIRCULAR): |
1318 | return SetCircular(pdx, (TRANSFERDESC __user *) ulArg); | |
2eae6bdc | 1319 | |
cd915200 GKH |
1320 | case _IOC_NR(IOCTL_CED_GETCIRCBLOCK): |
1321 | return GetCircBlock(pdx, (TCIRCBLOCK __user *) ulArg); | |
2eae6bdc | 1322 | |
cd915200 GKH |
1323 | case _IOC_NR(IOCTL_CED_FREECIRCBLOCK): |
1324 | return FreeCircBlock(pdx, (TCIRCBLOCK __user *) ulArg); | |
2eae6bdc | 1325 | |
cd915200 GKH |
1326 | case _IOC_NR(IOCTL_CED_WAITEVENT): |
1327 | return WaitEvent(pdx, (int)(ulArg & 0xff), (int)(ulArg >> 8)); | |
2eae6bdc | 1328 | |
cd915200 GKH |
1329 | case _IOC_NR(IOCTL_CED_TESTEVENT): |
1330 | return TestEvent(pdx, (int)ulArg); | |
2eae6bdc | 1331 | |
cd915200 GKH |
1332 | default: |
1333 | return U14ERR_NO_SUCH_FN; | |
1334 | } | |
1335 | return U14ERR_NOERROR; | |
2eae6bdc AS |
1336 | } |
1337 | ||
cd915200 GKH |
1338 | static const struct file_operations ced_fops = { |
1339 | .owner = THIS_MODULE, | |
cd915200 GKH |
1340 | .open = ced_open, |
1341 | .release = ced_release, | |
1342 | .flush = ced_flush, | |
1343 | .llseek = noop_llseek, | |
cd915200 | 1344 | .unlocked_ioctl = ced_ioctl, |
2eae6bdc AS |
1345 | }; |
1346 | ||
1347 | /* | |
1348 | * usb class driver info in order to get a minor number from the usb core, | |
1349 | * and to have the device registered with the driver core | |
1350 | */ | |
cd915200 GKH |
1351 | static struct usb_class_driver ced_class = { |
1352 | .name = "cedusb%d", | |
1353 | .fops = &ced_fops, | |
1354 | .minor_base = USB_CED_MINOR_BASE, | |
2eae6bdc AS |
1355 | }; |
1356 | ||
e4837704 EU |
1357 | /* Check that the device that matches a 1401 vendor and product ID is OK to use and */ |
1358 | /* initialise our DEVICE_EXTENSION. */ | |
cd915200 GKH |
1359 | static int ced_probe(struct usb_interface *interface, |
1360 | const struct usb_device_id *id) | |
2eae6bdc | 1361 | { |
cd915200 GKH |
1362 | DEVICE_EXTENSION *pdx; |
1363 | struct usb_host_interface *iface_desc; | |
1364 | struct usb_endpoint_descriptor *endpoint; | |
1365 | int i, bcdDevice; | |
1366 | int retval = -ENOMEM; | |
1367 | ||
e4837704 | 1368 | /* allocate memory for our device extension and initialize it */ |
cd915200 | 1369 | pdx = kzalloc(sizeof(*pdx), GFP_KERNEL); |
78110bb8 | 1370 | if (!pdx) |
cd915200 | 1371 | goto error; |
cd915200 | 1372 | |
e035b590 | 1373 | for (i = 0; i < MAX_TRANSAREAS; ++i) { /* Initialise the wait queues */ |
cd915200 GKH |
1374 | init_waitqueue_head(&pdx->rTransDef[i].wqEvent); |
1375 | } | |
1376 | ||
e4837704 EU |
1377 | /* Put initialises for our stuff here. Note that all of *pdx is zero, so */ |
1378 | /* no need to explicitly zero it. */ | |
cd915200 GKH |
1379 | spin_lock_init(&pdx->charOutLock); |
1380 | spin_lock_init(&pdx->charInLock); | |
1381 | spin_lock_init(&pdx->stagedLock); | |
1382 | ||
e4837704 | 1383 | /* Initialises from the skeleton stuff */ |
cd915200 GKH |
1384 | kref_init(&pdx->kref); |
1385 | mutex_init(&pdx->io_mutex); | |
1386 | spin_lock_init(&pdx->err_lock); | |
1387 | init_usb_anchor(&pdx->submitted); | |
1388 | ||
1389 | pdx->udev = usb_get_dev(interface_to_usbdev(interface)); | |
1390 | pdx->interface = interface; | |
1391 | ||
e4837704 | 1392 | /* Attempt to identify the device */ |
cd915200 GKH |
1393 | bcdDevice = pdx->udev->descriptor.bcdDevice; |
1394 | i = (bcdDevice >> 8); | |
1395 | if (i == 0) | |
1396 | pdx->s1401Type = TYPEU1401; | |
1397 | else if ((i >= 1) && (i <= 23)) | |
1398 | pdx->s1401Type = i + 2; | |
1399 | else { | |
1400 | dev_err(&interface->dev, "%s Unknown device. bcdDevice = %d", | |
1401 | __func__, bcdDevice); | |
1402 | goto error; | |
1403 | } | |
e4837704 EU |
1404 | /* set up the endpoint information. We only care about the number of EP as */ |
1405 | /* we know that we are dealing with a 1401 device. */ | |
cd915200 GKH |
1406 | iface_desc = interface->cur_altsetting; |
1407 | pdx->nPipes = iface_desc->desc.bNumEndpoints; | |
1408 | dev_info(&interface->dev, "1401Type=%d with %d End Points", | |
1409 | pdx->s1401Type, pdx->nPipes); | |
1410 | if ((pdx->nPipes < 3) || (pdx->nPipes > 4)) | |
1411 | goto error; | |
1412 | ||
e4837704 EU |
1413 | /* Allocate the URBs we hold for performing transfers */ |
1414 | pdx->pUrbCharOut = usb_alloc_urb(0, GFP_KERNEL); /* character output URB */ | |
1415 | pdx->pUrbCharIn = usb_alloc_urb(0, GFP_KERNEL); /* character input URB */ | |
1416 | pdx->pStagedUrb = usb_alloc_urb(0, GFP_KERNEL); /* block transfer URB */ | |
cd915200 GKH |
1417 | if (!pdx->pUrbCharOut || !pdx->pUrbCharIn || !pdx->pStagedUrb) { |
1418 | dev_err(&interface->dev, "%s URB alloc failed", __func__); | |
1419 | goto error; | |
1420 | } | |
1421 | ||
1422 | pdx->pCoherStagedIO = | |
1423 | usb_alloc_coherent(pdx->udev, STAGED_SZ, GFP_KERNEL, | |
1424 | &pdx->pStagedUrb->transfer_dma); | |
1425 | pdx->pCoherCharOut = | |
1426 | usb_alloc_coherent(pdx->udev, OUTBUF_SZ, GFP_KERNEL, | |
1427 | &pdx->pUrbCharOut->transfer_dma); | |
1428 | pdx->pCoherCharIn = | |
1429 | usb_alloc_coherent(pdx->udev, INBUF_SZ, GFP_KERNEL, | |
1430 | &pdx->pUrbCharIn->transfer_dma); | |
1431 | if (!pdx->pCoherCharOut || !pdx->pCoherCharIn || !pdx->pCoherStagedIO) { | |
1432 | dev_err(&interface->dev, "%s Coherent buffer alloc failed", | |
1433 | __func__); | |
1434 | goto error; | |
1435 | } | |
1436 | ||
1437 | for (i = 0; i < pdx->nPipes; ++i) { | |
1438 | endpoint = &iface_desc->endpoint[i].desc; | |
1439 | pdx->epAddr[i] = endpoint->bEndpointAddress; | |
1440 | dev_info(&interface->dev, "Pipe %d, ep address %02x", i, | |
1441 | pdx->epAddr[i]); | |
e4837704 | 1442 | if (((pdx->nPipes == 3) && (i == 0)) || /* if char input end point */ |
cd915200 | 1443 | ((pdx->nPipes == 4) && (i == 1))) { |
e4837704 | 1444 | pdx->bInterval = endpoint->bInterval; /* save the endpoint interrupt interval */ |
cd915200 GKH |
1445 | dev_info(&interface->dev, "Pipe %d, bInterval = %d", i, |
1446 | pdx->bInterval); | |
1447 | } | |
e4837704 | 1448 | /* Detect USB2 by checking last ep size (64 if USB1) */ |
e035b590 | 1449 | if (i == pdx->nPipes - 1) { /* if this is the last ep (bulk) */ |
cd915200 GKH |
1450 | pdx->bIsUSB2 = |
1451 | le16_to_cpu(endpoint->wMaxPacketSize) > 64; | |
1452 | dev_info(&pdx->interface->dev, "USB%d", | |
1453 | pdx->bIsUSB2 + 1); | |
1454 | } | |
1455 | } | |
1456 | ||
1457 | /* save our data pointer in this interface device */ | |
1458 | usb_set_intfdata(interface, pdx); | |
1459 | ||
1460 | /* we can register the device now, as it is ready */ | |
1461 | retval = usb_register_dev(interface, &ced_class); | |
1462 | if (retval) { | |
1463 | /* something prevented us from registering this driver */ | |
1464 | dev_err(&interface->dev, | |
1465 | "Not able to get a minor for this device.\n"); | |
1466 | usb_set_intfdata(interface, NULL); | |
1467 | goto error; | |
1468 | } | |
1469 | ||
1470 | /* let the user know what node this device is now attached to */ | |
1471 | dev_info(&interface->dev, | |
1472 | "USB CEDUSB device now attached to cedusb #%d", | |
1473 | interface->minor); | |
1474 | return 0; | |
2eae6bdc AS |
1475 | |
1476 | error: | |
cd915200 | 1477 | if (pdx) |
e4837704 | 1478 | kref_put(&pdx->kref, ced_delete); /* frees allocated memory */ |
cd915200 | 1479 | return retval; |
2eae6bdc AS |
1480 | } |
1481 | ||
1482 | static void ced_disconnect(struct usb_interface *interface) | |
1483 | { | |
cd915200 | 1484 | DEVICE_EXTENSION *pdx = usb_get_intfdata(interface); |
ff549e47 | 1485 | int minor = interface->minor; |
cd915200 GKH |
1486 | int i; |
1487 | ||
e4837704 EU |
1488 | usb_set_intfdata(interface, NULL); /* remove the pdx from the interface */ |
1489 | usb_deregister_dev(interface, &ced_class); /* give back our minor device number */ | |
cd915200 | 1490 | |
e4837704 EU |
1491 | mutex_lock(&pdx->io_mutex); /* stop more I/O starting while... */ |
1492 | ced_draw_down(pdx); /* ...wait for then kill any io */ | |
cd915200 | 1493 | for (i = 0; i < MAX_TRANSAREAS; ++i) { |
e4837704 | 1494 | int iErr = ClearArea(pdx, i); /* ...release any used memory */ |
cd915200 GKH |
1495 | if (iErr == U14ERR_UNLOCKFAIL) |
1496 | dev_err(&pdx->interface->dev, "%s Area %d was in used", | |
1497 | __func__, i); | |
1498 | } | |
e4837704 | 1499 | pdx->interface = NULL; /* ...we kill off link to interface */ |
cd915200 | 1500 | mutex_unlock(&pdx->io_mutex); |
2eae6bdc | 1501 | |
cd915200 | 1502 | usb_kill_anchored_urbs(&pdx->submitted); |
2eae6bdc | 1503 | |
e4837704 | 1504 | kref_put(&pdx->kref, ced_delete); /* decrement our usage count */ |
2eae6bdc | 1505 | |
cd915200 | 1506 | dev_info(&interface->dev, "USB cedusb #%d now disconnected", minor); |
2eae6bdc AS |
1507 | } |
1508 | ||
e4837704 EU |
1509 | /* Wait for all the urbs we know of to be done with, then kill off any that */ |
1510 | /* are left. NBNB we will need to have a mechanism to stop circular xfers */ | |
1511 | /* from trying to fire off more urbs. We will wait up to 3 seconds for Urbs */ | |
1512 | /* to be done. */ | |
d1cc1b86 | 1513 | void ced_draw_down(DEVICE_EXTENSION *pdx) |
2eae6bdc | 1514 | { |
cd915200 GKH |
1515 | int time; |
1516 | dev_dbg(&pdx->interface->dev, "%s called", __func__); | |
1517 | ||
1518 | pdx->bInDrawDown = true; | |
1519 | time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000); | |
e4837704 | 1520 | if (!time) { /* if we timed out we kill the urbs */ |
cd915200 GKH |
1521 | usb_kill_anchored_urbs(&pdx->submitted); |
1522 | dev_err(&pdx->interface->dev, "%s timed out", __func__); | |
1523 | } | |
1524 | pdx->bInDrawDown = false; | |
1525 | } | |
2eae6bdc AS |
1526 | |
1527 | static int ced_suspend(struct usb_interface *intf, pm_message_t message) | |
1528 | { | |
cd915200 GKH |
1529 | DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); |
1530 | if (!pdx) | |
1531 | return 0; | |
1532 | ced_draw_down(pdx); | |
2eae6bdc | 1533 | |
cd915200 GKH |
1534 | dev_dbg(&pdx->interface->dev, "%s called", __func__); |
1535 | return 0; | |
2eae6bdc AS |
1536 | } |
1537 | ||
1538 | static int ced_resume(struct usb_interface *intf) | |
1539 | { | |
cd915200 GKH |
1540 | DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); |
1541 | if (!pdx) | |
1542 | return 0; | |
1543 | dev_dbg(&pdx->interface->dev, "%s called", __func__); | |
1544 | return 0; | |
2eae6bdc AS |
1545 | } |
1546 | ||
1547 | static int ced_pre_reset(struct usb_interface *intf) | |
1548 | { | |
cd915200 GKH |
1549 | DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); |
1550 | dev_dbg(&pdx->interface->dev, "%s", __func__); | |
1551 | mutex_lock(&pdx->io_mutex); | |
1552 | ced_draw_down(pdx); | |
1553 | return 0; | |
2eae6bdc AS |
1554 | } |
1555 | ||
1556 | static int ced_post_reset(struct usb_interface *intf) | |
1557 | { | |
cd915200 GKH |
1558 | DEVICE_EXTENSION *pdx = usb_get_intfdata(intf); |
1559 | dev_dbg(&pdx->interface->dev, "%s", __func__); | |
2eae6bdc | 1560 | |
cd915200 GKH |
1561 | /* we are sure no URBs are active - no locking needed */ |
1562 | pdx->errors = -EPIPE; | |
1563 | mutex_unlock(&pdx->io_mutex); | |
2eae6bdc | 1564 | |
cd915200 | 1565 | return 0; |
2eae6bdc AS |
1566 | } |
1567 | ||
cd915200 GKH |
1568 | static struct usb_driver ced_driver = { |
1569 | .name = "cedusb", | |
1570 | .probe = ced_probe, | |
1571 | .disconnect = ced_disconnect, | |
1572 | .suspend = ced_suspend, | |
1573 | .resume = ced_resume, | |
1574 | .pre_reset = ced_pre_reset, | |
1575 | .post_reset = ced_post_reset, | |
1576 | .id_table = ced_table, | |
1577 | .supports_autosuspend = 1, | |
2eae6bdc AS |
1578 | }; |
1579 | ||
2341111f | 1580 | module_usb_driver(ced_driver); |
2eae6bdc | 1581 | MODULE_LICENSE("GPL"); |