OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [parport/] [probe.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.