dt/sparc: Eliminate users of of_platform_{,un}register_driver
[linux-2.6.git] / drivers / parport / probe.c
1 /*
2  * Parallel port device probing code
3  *
4  * Authors:    Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
5  *             Philip Blundell <philb@gnu.org>
6  */
7
8 #include <linux/module.h>
9 #include <linux/parport.h>
10 #include <linux/ctype.h>
11 #include <linux/string.h>
12 #include <linux/slab.h>
13 #include <asm/uaccess.h>
14
15 static const struct {
16         const char *token;
17         const char *descr;
18 } classes[] = {
19         { "",            "Legacy device" },
20         { "PRINTER",     "Printer" },
21         { "MODEM",       "Modem" },
22         { "NET",         "Network device" },
23         { "HDC",         "Hard disk" },
24         { "PCMCIA",      "PCMCIA" },
25         { "MEDIA",       "Multimedia device" },
26         { "FDC",         "Floppy disk" },
27         { "PORTS",       "Ports" },
28         { "SCANNER",     "Scanner" },
29         { "DIGICAM",     "Digital camera" },
30         { "",            "Unknown device" },
31         { "",            "Unspecified" },
32         { "SCSIADAPTER", "SCSI adapter" },
33         { NULL,          NULL }
34 };
35
36 static void pretty_print(struct parport *port, int device)
37 {
38         struct parport_device_info *info = &port->probe_info[device + 1];
39
40         printk(KERN_INFO "%s", port->name);
41
42         if (device >= 0)
43                 printk (" (addr %d)", device);
44
45         printk (": %s", classes[info->class].descr);
46         if (info->class)
47                 printk(", %s %s", info->mfr, info->model);
48
49         printk("\n");
50 }
51
52 static void parse_data(struct parport *port, int device, char *str)
53 {
54         char *txt = kmalloc(strlen(str)+1, GFP_KERNEL);
55         char *p = txt, *q;
56         int guessed_class = PARPORT_CLASS_UNSPEC;
57         struct parport_device_info *info = &port->probe_info[device + 1];
58
59         if (!txt) {
60                 printk(KERN_WARNING "%s probe: memory squeeze\n", port->name);
61                 return;
62         }
63         strcpy(txt, str);
64         while (p) {
65                 char *sep;
66                 q = strchr(p, ';');
67                 if (q) *q = 0;
68                 sep = strchr(p, ':');
69                 if (sep) {
70                         char *u;
71                         *(sep++) = 0;
72                         /* Get rid of trailing blanks */
73                         u = sep + strlen (sep) - 1;
74                         while (u >= p && *u == ' ')
75                                 *u-- = '\0';
76                         u = p;
77                         while (*u) {
78                                 *u = toupper(*u);
79                                 u++;
80                         }
81                         if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
82                                 kfree(info->mfr);
83                                 info->mfr = kstrdup(sep, GFP_KERNEL);
84                         } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
85                                 kfree(info->model);
86                                 info->model = kstrdup(sep, GFP_KERNEL);
87                         } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
88                                 int i;
89
90                                 kfree(info->class_name);
91                                 info->class_name = kstrdup(sep, GFP_KERNEL);
92                                 for (u = sep; *u; u++)
93                                         *u = toupper(*u);
94                                 for (i = 0; classes[i].token; i++) {
95                                         if (!strcmp(classes[i].token, sep)) {
96                                                 info->class = i;
97                                                 goto rock_on;
98                                         }
99                                 }
100                                 printk(KERN_WARNING "%s probe: warning, class '%s' not understood.\n", port->name, sep);
101                                 info->class = PARPORT_CLASS_OTHER;
102                         } else if (!strcmp(p, "CMD") ||
103                                    !strcmp(p, "COMMAND SET")) {
104                                 kfree(info->cmdset);
105                                 info->cmdset = kstrdup(sep, GFP_KERNEL);
106                                 /* if it speaks printer language, it's
107                                    probably a printer */
108                                 if (strstr(sep, "PJL") || strstr(sep, "PCL"))
109                                         guessed_class = PARPORT_CLASS_PRINTER;
110                         } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
111                                 kfree(info->description);
112                                 info->description = kstrdup(sep, GFP_KERNEL);
113                         }
114                 }
115         rock_on:
116                 if (q)
117                         p = q + 1;
118                 else
119                         p = NULL;
120         }
121
122         /* If the device didn't tell us its class, maybe we have managed to
123            guess one from the things it did say. */
124         if (info->class == PARPORT_CLASS_UNSPEC)
125                 info->class = guessed_class;
126
127         pretty_print (port, device);
128
129         kfree(txt);
130 }
131
132 /* Read up to count-1 bytes of device id. Terminate buffer with
133  * '\0'. Buffer begins with two Device ID length bytes as given by
134  * device. */
135 static ssize_t parport_read_device_id (struct parport *port, char *buffer,
136                                        size_t count)
137 {
138         unsigned char length[2];
139         unsigned lelen, belen;
140         size_t idlens[4];
141         unsigned numidlens;
142         unsigned current_idlen;
143         ssize_t retval;
144         size_t len;
145
146         /* First two bytes are MSB,LSB of inclusive length. */
147         retval = parport_read (port, length, 2);
148
149         if (retval < 0)
150                 return retval;
151         if (retval != 2)
152                 return -EIO;
153
154         if (count < 2)
155                 return 0;
156         memcpy(buffer, length, 2);
157         len = 2;
158
159         /* Some devices wrongly send LE length, and some send it two
160          * bytes short. Construct a sorted array of lengths to try. */
161         belen = (length[0] << 8) + length[1];
162         lelen = (length[1] << 8) + length[0];
163         idlens[0] = min(belen, lelen);
164         idlens[1] = idlens[0]+2;
165         if (belen != lelen) {
166                 int off = 2;
167                 /* Don't try lengths of 0x100 and 0x200 as 1 and 2 */
168                 if (idlens[0] <= 2)
169                         off = 0;
170                 idlens[off] = max(belen, lelen);
171                 idlens[off+1] = idlens[off]+2;
172                 numidlens = off+2;
173         }
174         else {
175                 /* Some devices don't truly implement Device ID, but
176                  * just return constant nibble forever. This catches
177                  * also those cases. */
178                 if (idlens[0] == 0 || idlens[0] > 0xFFF) {
179                         printk (KERN_DEBUG "%s: reported broken Device ID"
180                                 " length of %#zX bytes\n",
181                                 port->name, idlens[0]);
182                         return -EIO;
183                 }
184                 numidlens = 2;
185         }
186
187         /* Try to respect the given ID length despite all the bugs in
188          * the ID length. Read according to shortest possible ID
189          * first. */
190         for (current_idlen = 0; current_idlen < numidlens; ++current_idlen) {
191                 size_t idlen = idlens[current_idlen];
192                 if (idlen+1 >= count)
193                         break;
194
195                 retval = parport_read (port, buffer+len, idlen-len);
196
197                 if (retval < 0)
198                         return retval;
199                 len += retval;
200
201                 if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) {
202                         if (belen != len) {
203                                 printk (KERN_DEBUG "%s: Device ID was %zd bytes"
204                                         " while device told it would be %d"
205                                         " bytes\n",
206                                         port->name, len, belen);
207                         }
208                         goto done;
209                 }
210
211                 /* This might end reading the Device ID too
212                  * soon. Hopefully the needed fields were already in
213                  * the first 256 bytes or so that we must have read so
214                  * far. */
215                 if (buffer[len-1] == ';') {
216                         printk (KERN_DEBUG "%s: Device ID reading stopped"
217                                 " before device told data not available. "
218                                 "Current idlen %u of %u, len bytes %02X %02X\n",
219                                 port->name, current_idlen, numidlens,
220                                 length[0], length[1]);
221                         goto done;
222                 }
223         }
224         if (current_idlen < numidlens) {
225                 /* Buffer not large enough, read to end of buffer. */
226                 size_t idlen, len2;
227                 if (len+1 < count) {
228                         retval = parport_read (port, buffer+len, count-len-1);
229                         if (retval < 0)
230                                 return retval;
231                         len += retval;
232                 }
233                 /* Read the whole ID since some devices would not
234                  * otherwise give back the Device ID from beginning
235                  * next time when asked. */
236                 idlen = idlens[current_idlen];
237                 len2 = len;
238                 while(len2 < idlen && retval > 0) {
239                         char tmp[4];
240                         retval = parport_read (port, tmp,
241                                                min(sizeof tmp, idlen-len2));
242                         if (retval < 0)
243                                 return retval;
244                         len2 += retval;
245                 }
246         }
247         /* In addition, there are broken devices out there that don't
248            even finish off with a semi-colon. We do not need to care
249            about those at this time. */
250  done:
251         buffer[len] = '\0';
252         return len;
253 }
254
255 /* Get Std 1284 Device ID. */
256 ssize_t parport_device_id (int devnum, char *buffer, size_t count)
257 {
258         ssize_t retval = -ENXIO;
259         struct pardevice *dev = parport_open (devnum, "Device ID probe");
260         if (!dev)
261                 return -ENXIO;
262
263         parport_claim_or_block (dev);
264
265         /* Negotiate to compatibility mode, and then to device ID
266          * mode. (This so that we start form beginning of device ID if
267          * already in device ID mode.) */
268         parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
269         retval = parport_negotiate (dev->port,
270                                     IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
271
272         if (!retval) {
273                 retval = parport_read_device_id (dev->port, buffer, count);
274                 parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
275                 if (retval > 2)
276                         parse_data (dev->port, dev->daisy, buffer+2);
277         }
278
279         parport_release (dev);
280         parport_close (dev);
281         return retval;
282 }