Revert "Remove support for xpp drivers."
[dahdi/linux.git] / drivers / dahdi / xpp / card_global.c
1 /*
2  * Written by Oron Peled <oron@actcom.co.il>
3  * Copyright (C) 2004-2006, Xorcom
4  *
5  * All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #include <linux/module.h>
24 #include <linux/delay.h>
25 #include <linux/kmod.h>
26 #include "xdefs.h"
27 #include "xpd.h"
28 #include "xpp_dahdi.h"
29 #include "xproto.h"
30 #include "dahdi_debug.h"
31 #include "xbus-core.h"
32 #include "parport_debug.h"
33
34 static const char rcsid[] = "$Id$";
35
36 DEF_PARM(charp, initdir, "/usr/share/dahdi", 0644,
37          "The directory of card initialization scripts");
38
39 #define CHIP_REGISTERS  "chipregs"
40
41 extern int debug;
42
43 /*---------------- GLOBAL PROC handling -----------------------------------*/
44
45 static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
46                               bool eoftx)
47 {
48         xframe_t *xframe;
49         xpacket_t *pack;
50         reg_cmd_t *reg_cmd;
51         int ret;
52
53         /*
54          * Zero length multibyte is legal and has special meaning for the
55          * firmware:
56          *   eoftx==1: Start sending us D-channel packets.
57          *   eoftx==0: Stop sending us D-channel packets.
58          */
59         XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, unit);
60         reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
61         reg_cmd->h.bytes = 0;
62         reg_cmd->h.is_multibyte = 1;
63         reg_cmd->h.portnum = portno;
64         reg_cmd->h.eoframe = eoftx;
65         PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
66         if (debug & DBG_REGS)
67                 dump_xframe(__func__, xbus, xframe, debug);
68         ret = send_cmd_frame(xbus, xframe);
69         if (ret < 0)
70                 PORT_ERR(xbus, unit, portno, "%s: failed sending xframe\n",
71                          __func__);
72         return ret;
73 }
74
75 static int parse_hexbyte(const char *buf)
76 {
77         char *endp;
78         unsigned val;
79
80         val = simple_strtoul(buf, &endp, 16);
81         if (*endp != '\0' || val > 0xFF)
82                 return -EBADR;
83         return (__u8)val;
84 }
85
86 static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
87 {
88         int argno;
89         char num_args;
90         int portno;
91         bool writing;
92         int op;                 /* [W]rite, [R]ead */
93         int addr_mode;          /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */
94         bool do_subreg = 0;
95         int regnum;
96         int subreg;
97         int data_low;
98         bool do_datah;
99         int data_high;
100         bool do_expander = 0;
101         int ret = -EBADR;
102
103         num_args = 2;           /* port + operation */
104         if (argc < num_args) {
105                 XPD_ERR(xpd, "Not enough arguments (%d)\n", argc);
106                 XPD_ERR(xpd,
107                         "Any Command is composed of at least %d words "
108                         "(got only %d)\n",
109                         num_args, argc);
110                 goto out;
111         }
112         /* Process the arguments */
113         argno = 0;
114         if (strcmp(argv[argno], "*") == 0) {
115                 portno = PORT_BROADCAST;
116                 //XPD_DBG(REGS, xpd, "Port broadcast\n");
117         } else {
118                 portno = parse_hexbyte(argv[argno]);
119                 if (portno < 0 || portno >= 8) {
120                         XPD_ERR(xpd, "Illegal port number '%s'\n", argv[argno]);
121                         goto out;
122                 }
123                 //XPD_DBG(REGS, xpd, "Port is %d\n", portno);
124         }
125         argno++;
126         if (strlen(argv[argno]) != 2) {
127                 XPD_ERR(xpd, "Wrong operation codes '%s'\n", argv[argno]);
128                 goto out;
129         }
130         op = argv[argno][0];
131         switch (op) {
132         case 'W':
133                 writing = 1;
134                 num_args++;     /* data low */
135                 //XPD_DBG(REGS, xpd, "WRITING\n");
136                 break;
137         case 'R':
138                 writing = 0;
139                 //XPD_DBG(REGS, xpd, "READING\n");
140                 break;
141         default:
142                 XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
143                 goto out;
144         }
145         addr_mode = argv[argno][1];
146         switch (addr_mode) {
147         case 'I':
148                 XPD_NOTICE(xpd,
149                         "'I' is deprecated in register commands. "
150                         "Use 'S' instead.\n");
151                 /* fall through */
152         case 'S':
153                 do_subreg = 1;
154                 num_args += 2;  /* register + subreg */
155                 //XPD_DBG(REGS, xpd, "SUBREG\n");
156                 break;
157         case 'D':
158                 do_subreg = 0;
159                 num_args++;     /* register */
160                 //XPD_DBG(REGS, xpd, "DIRECT\n");
161                 break;
162         case 'X':
163                 do_subreg = 0;
164                 do_expander = 1;
165                 num_args++;     /* register */
166                 //XPD_DBG(REGS, xpd, "EXPANDER\n");
167                 break;
168         case 'M':
169         case 'm':
170                 if (op != 'W') {
171                         XPD_ERR(xpd,
172                                 "Can use Multibyte (%c) only with op 'W'\n",
173                                 addr_mode);
174                         goto out;
175                 }
176                 num_args--;     /* No data low */
177                 //XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
178                 break;
179         case 'R':
180                 switch (op) {
181                 case 'W':
182                         num_args += 5;  /* add: addr_high, data_[0-3] */
183                         break;
184                 case 'R':
185                         num_args += 2;  /* add: addr_low, addr_high */
186                         break;
187                 }
188                 break;
189         default:
190                 XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
191                 goto out;
192         }
193         if (argv[argno][2] != '\0') {
194                 XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]);
195                 goto out;
196         }
197         if (argc < num_args) {
198                 XPD_ERR(xpd,
199                         "Command \"%s\" is composed of at least %d words "
200                         "(got only %d)\n",
201                         argv[argno], num_args, argc);
202                 goto out;
203         }
204         argno++;
205         if (addr_mode == 'M' || addr_mode == 'm') {
206                 if (argno < argc) {
207                         XPD_ERR(xpd,
208                                 "Magic-Multibyte(%c) with %d extra arguments\n",
209                                 addr_mode, argc - argno);
210                         goto out;
211                 }
212                 ret =
213                     send_magic_request(xpd->xbus, xpd->addr.unit, portno,
214                                        addr_mode == 'm');
215                 goto out;
216         }
217         if (addr_mode == 'R') {
218                 __u8 input[6];
219                 int i;
220
221                 if (num_args - 2 > 6) {
222                         XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2);
223                         goto out;
224                 }
225                 for (i = 0; i < num_args - 2; i++, argno++) {
226                         int hexbyte= parse_hexbyte(argv[argno]);
227                         if (hexbyte < 0) {
228                                 XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]);
229                                 goto out;
230                         }
231                         input[i] = hexbyte;
232                 }
233                 ret = xpp_ram_request(xpd->xbus, xpd, portno, writing,
234                         input[0],
235                         input[1],
236                         input[2],
237                         input[3],
238                         input[4],
239                         input[5],
240                         1);
241                 goto out;
242         }
243         /* Normal (non-Magic) register commands */
244         do_datah = 0;
245         if (argno >= argc) {
246                 XPD_ERR(xpd, "Missing register number\n");
247                 goto out;
248         }
249         regnum = parse_hexbyte(argv[argno]);
250         if (regnum < 0) {
251                 XPD_ERR(xpd, "Illegal register number '%s'\n", argv[argno]);
252                 goto out;
253         }
254         //XPD_DBG(REGS, xpd, "Register is %X\n", regnum);
255         argno++;
256         if (do_subreg) {
257                 if (argno >= argc) {
258                         XPD_ERR(xpd, "Missing subregister number\n");
259                         goto out;
260                 }
261                 subreg = parse_hexbyte(argv[argno]);
262                 if (subreg < 0) {
263                         XPD_ERR(xpd, "Illegal subregister number '%s'\n",
264                                 argv[argno]);
265                         goto out;
266                 }
267                 //XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg);
268                 argno++;
269         } else
270                 subreg = 0;
271         if (writing) {
272                 if (argno >= argc) {
273                         XPD_ERR(xpd, "Missing data low number\n");
274                         goto out;
275                 }
276                 data_low = parse_hexbyte(argv[argno]);
277                 if (data_low < 0) {
278                         XPD_ERR(xpd, "Illegal data_low number '%s'\n",
279                                 argv[argno]);
280                         goto out;
281                 }
282                 //XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low);
283                 argno++;
284         } else
285                 data_low = 0;
286         if (argno < argc) {
287                 do_datah = 1;
288                 if (!argv[argno]) {
289                         XPD_ERR(xpd, "Missing data high number\n");
290                         goto out;
291                 }
292                 data_high = parse_hexbyte(argv[argno]);
293                 if (data_high < 0) {
294                         XPD_ERR(xpd, "Illegal data_high number '%s'\n",
295                                 argv[argno]);
296                         goto out;
297                 }
298                 //XPD_DBG(REGS, xpd, "Data High is %X\n", data_high);
299                 argno++;
300         } else
301                 data_high = 0;
302         if (argno < argc) {
303                 XPD_ERR(xpd, "Command contains an extra %d argument\n",
304                         argc - argno);
305                 goto out;
306         }
307 #if 0
308         XPD_DBG(REGS, xpd,
309                 "portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
310                 "dataL=%d do_datah=%d dataH=%d do_expander=%d\n",
311                 portno,                 /* portno       */
312                 writing,                /* writing      */
313                 regnum, do_subreg,      /* use subreg   */
314                 subreg,                 /* subreg       */
315                 data_low, do_datah,     /* use data_high */
316                 data_high, do_expander);
317 #endif
318         ret = xpp_register_request(xpd->xbus, xpd, portno,
319                 writing, regnum, do_subreg, subreg,
320                 data_low, do_datah, data_high, 1, do_expander);
321 out:
322         return ret;
323 }
324
325 #define MAX_ARGS        10
326
327 int parse_chip_command(xpd_t *xpd, char *cmdline)
328 {
329         xbus_t *xbus;
330         int ret = -EBADR;
331         __u8 buf[MAX_PROC_WRITE];
332         char *str;
333         char *p;
334         char *argv[MAX_ARGS + 1];
335         int argc;
336         int i;
337
338         BUG_ON(!xpd);
339         xbus = xpd->xbus;
340         if (!XBUS_FLAGS(xbus, CONNECTED)) {
341                 XBUS_DBG(GENERAL, xbus, "Dropped packet. Disconnected.\n");
342                 return -EBUSY;
343         }
344         strlcpy(buf, cmdline, MAX_PROC_WRITE);  /* Save a copy */
345         if (buf[0] == '#' || buf[0] == ';')
346                 XPD_DBG(REGS, xpd, "Note: '%s'\n", buf);
347         if ((p = strchr(buf, '#')) != NULL)     /* Truncate comments */
348                 *p = '\0';
349         if ((p = strchr(buf, ';')) != NULL)     /* Truncate comments */
350                 *p = '\0';
351         /* Trim leading whitespace */
352         for (p = buf; *p && (*p == ' ' || *p == '\t'); p++)
353                 ;
354         str = p;
355         for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS;) {
356                 if (*p != '\0') {
357                         argv[i] = p;
358                         // XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p);
359                         i++;
360                 }
361         }
362         argv[i] = NULL;
363         argc = i;
364         if (p) {
365                 XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n",
366                         i, p);
367                 goto out;
368         }
369         if (argc)
370                 ret = execute_chip_command(xpd, argc, argv);
371         else
372                 ret = 0;        /* empty command - no op */
373 out:
374         return ret;
375 }
376
377 /*---------------- GLOBAL Protocol Commands -------------------------------*/
378
379 static bool global_packet_is_valid(xpacket_t *pack);
380 static void global_packet_dump(const char *msg, xpacket_t *pack);
381
382 /*---------------- GLOBAL: HOST COMMANDS ----------------------------------*/
383
384 /* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST)
385 {
386         int ret = -ENODEV;
387         xframe_t *xframe;
388         xpacket_t *pack;
389
390         if (!xbus) {
391                 DBG(DEVICES, "NO XBUS\n");
392                 return -EINVAL;
393         }
394         if (xbus_check_unique(xbus))
395                 return -EBUSY;
396         XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, AB_REQUEST, 0);
397         RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, rev) = XPP_PROTOCOL_VERSION;
398         RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, reserved) = 0;
399         XBUS_DBG(DEVICES, xbus, "Protocol Version %d\n", XPP_PROTOCOL_VERSION);
400         if (xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
401                 ret = send_cmd_frame(xbus, xframe);
402         return ret;
403 }
404
405 int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
406                          bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
407                          __u8 data_low, bool do_datah, __u8 data_high,
408                          bool should_reply, bool do_expander)
409 {
410         int ret = 0;
411         xframe_t *xframe;
412         xpacket_t *pack;
413         reg_cmd_t *reg_cmd;
414
415         if (!xbus) {
416                 DBG(REGS, "NO XBUS\n");
417                 return -EINVAL;
418         }
419         XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, xpd->xbus_idx);
420         LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
421                  (writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
422                  data_low, data_high);
423         reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
424         /* do not count the 'bytes' field */
425         reg_cmd->h.bytes = REG_CMD_SIZE(REG);
426         reg_cmd->h.is_multibyte = 0;
427         if (portno == PORT_BROADCAST) {
428                 reg_cmd->h.portnum = 0;
429                 REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
430         } else {
431                 reg_cmd->h.portnum = portno;
432                 REG_FIELD(reg_cmd, all_ports_broadcast) = 0;
433         }
434         reg_cmd->h.eoframe = 0;
435         REG_FIELD(reg_cmd, reserved) = 0;       /* force reserved bits to 0 */
436         REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
437         REG_FIELD(reg_cmd, do_subreg) = do_subreg;
438         REG_FIELD(reg_cmd, regnum) = regnum;
439         REG_FIELD(reg_cmd, subreg) = subreg;
440         REG_FIELD(reg_cmd, do_datah) = do_datah;
441         REG_FIELD(reg_cmd, data_low) = data_low;
442         REG_FIELD(reg_cmd, data_high) = data_high;
443         REG_FIELD(reg_cmd, do_expander) = do_expander;
444         if (should_reply)
445                 xpd->requested_reply = *reg_cmd;
446         if (debug & DBG_REGS) {
447                 dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
448                              reg_cmd->h.portnum, reg_cmd);
449                 dump_packet("REG_REQ", pack, 1);
450         }
451         if (!xframe->usec_towait) {     /* default processing time of SPI */
452                 if (subreg)
453                         xframe->usec_towait = 2000;
454                 else
455                         xframe->usec_towait = 1000;
456         }
457         ret = send_cmd_frame(xbus, xframe);
458         return ret;
459 }
460 EXPORT_SYMBOL(xpp_register_request);
461
462 int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
463                          bool writing,
464                         __u8 addr_low,
465                         __u8 addr_high,
466                         __u8 data_0,
467                         __u8 data_1,
468                         __u8 data_2,
469                         __u8 data_3,
470                          bool should_reply)
471 {
472         int ret = 0;
473         xframe_t *xframe;
474         xpacket_t *pack;
475         reg_cmd_t *reg_cmd;
476
477         if (!xbus) {
478                 DBG(REGS, "NO XBUS\n");
479                 return -EINVAL;
480         }
481         XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx);
482         LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n",
483                 (writing) ? 'W' : 'R',
484                 addr_low, addr_high,
485                 data_0, data_1, data_2, data_3);
486         reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
487         /* do not count the 'bytes' field */
488         reg_cmd->h.bytes = REG_CMD_SIZE(RAM);
489         reg_cmd->h.is_multibyte = 0;
490         if (portno == PORT_BROADCAST) {
491                 reg_cmd->h.portnum = 0;
492                 REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1;
493         } else {
494                 reg_cmd->h.portnum = portno;
495                 REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0;
496         }
497         reg_cmd->h.eoframe = 0;
498         REG_FIELD_RAM(reg_cmd, reserved) = 0;   /* force reserved bits to 0 */
499         REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1;
500         REG_FIELD_RAM(reg_cmd, do_datah) = 1;
501         REG_FIELD_RAM(reg_cmd, do_subreg) = 1;
502         REG_FIELD_RAM(reg_cmd, addr_low) = addr_low;
503         REG_FIELD_RAM(reg_cmd, addr_high) = addr_high;
504         REG_FIELD_RAM(reg_cmd, data_0) = data_0;
505         REG_FIELD_RAM(reg_cmd, data_1) = data_1;
506         REG_FIELD_RAM(reg_cmd, data_2) = data_2;
507         REG_FIELD_RAM(reg_cmd, data_3) = data_3;
508         if (should_reply)
509                 xpd->requested_reply = *reg_cmd;
510         if (debug & DBG_REGS) {
511                 dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit,
512                              reg_cmd->h.portnum, reg_cmd);
513                 dump_packet("REG_RAM", pack, 1);
514         }
515         if (!xframe->usec_towait) {     /* default processing time of SPI */
516                 xframe->usec_towait = 1000;
517         }
518         ret = send_cmd_frame(xbus, xframe);
519         return ret;
520 }
521 EXPORT_SYMBOL(xpp_ram_request);
522
523 /*
524  * The XPD parameter is totaly ignored by the driver and firmware as well.
525  */
526 /* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
527 {
528         xframe_t *xframe;
529         xpacket_t *pack;
530         const char *mode_name;
531
532         BUG_ON(!xbus);
533         if ((mode_name = sync_mode_name(mode)) == NULL) {
534                 XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode);
535                 return -EINVAL;
536         }
537         XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift);
538         XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, 0);
539         RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, sync_mode) = mode;
540         RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, drift) = drift;
541         send_cmd_frame(xbus, xframe);
542         return 0;
543 }
544
545 /*
546  * Wrapper for different types of xbus reset
547  */
548 static int send_xbus_reset(xbus_t *xbus, uint8_t reset_mask)
549 {
550         xframe_t *xframe;
551         xpacket_t *pack;
552
553         BUG_ON(!xbus);
554         XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, XBUS_RESET, 0);
555         RPACKET_FIELD(pack, GLOBAL, XBUS_RESET, mask) = reset_mask;
556         send_cmd_frame(xbus, xframe);
557         return 0;
558 }
559
560 /* 0x23 */ HOSTCMD(GLOBAL, RESET_SPI)
561 {
562         XBUS_DBG(DEVICES, xbus, "Sending SPI reset\n");
563         /* toggle reset line */
564         send_xbus_reset(xbus, 0x04);
565         send_xbus_reset(xbus, 0x00);
566         return 0;
567 }
568
569
570 /* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS)
571 {
572         //XBUS_DBG(SYNC, xbus, "\n");
573         return send_xbus_reset(xbus, 0x10);
574 }
575
576 /*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/
577
578 HANDLER_DEF(GLOBAL, NULL_REPLY)
579 {
580         XBUS_DBG(GENERAL, xbus, "got len=%d\n", XPACKET_LEN(pack));
581         return 0;
582 }
583
584 HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
585 {                               /* 0x08 */
586         struct xbus_workqueue *worker;
587         __u8 rev;
588         struct unit_descriptor *units;
589         int count_units;
590         int i;
591         int ret = 0;
592
593         if (!xbus) {
594                 NOTICE("%s: xbus is gone!!!\n", __func__);
595                 goto out;
596         }
597         rev = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, rev);
598         units = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, unit_descriptor);
599         count_units = XPACKET_LEN(pack) - ((__u8 *)units - (__u8 *)pack);
600         count_units /= sizeof(*units);
601         if (rev != XPP_PROTOCOL_VERSION) {
602                 XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n",
603                             rev, XPP_PROTOCOL_VERSION);
604                 ret = -EPROTO;
605                 goto proto_err;
606         }
607         if (count_units > NUM_UNITS) {
608                 XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n",
609                             count_units, NUM_UNITS);
610                 ret = -EPROTO;
611                 goto proto_err;
612         }
613         if (count_units <= 0) {
614                 XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n", count_units);
615                 ret = -EPROTO;
616                 goto proto_err;
617         }
618         if (units[0].addr.unit != 0 || units[0].addr.subunit != 0) {
619                 XBUS_NOTICE(xbus, "No first module. Astribank unusable.\n");
620                 ret = -EPROTO;
621                 goto proto_err;
622         }
623         if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
624                 ret = -EPROTO;
625                 goto proto_err;
626         }
627         XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n",
628                   count_units, rev);
629         if (xbus_check_unique(xbus))
630                 return -EBUSY;
631         xbus->revision = rev;
632         worker = &xbus->worker;
633         if (!worker->wq) {
634                 XBUS_ERR(xbus, "missing worker thread\n");
635                 ret = -ENODEV;
636                 goto out;
637         }
638         for (i = 0; i < count_units; i++) {
639                 struct unit_descriptor *this_unit = &units[i];
640                 struct card_desc_struct *card_desc;
641                 unsigned long flags;
642
643                 if ((card_desc =
644                      KZALLOC(sizeof(struct card_desc_struct),
645                              GFP_ATOMIC)) == NULL) {
646                         XBUS_ERR(xbus, "Card description allocation failed.\n");
647                         ret = -ENOMEM;
648                         goto out;
649                 }
650                 card_desc->magic = CARD_DESC_MAGIC;
651                 INIT_LIST_HEAD(&card_desc->card_list);
652                 card_desc->unit_descriptor = *this_unit;
653                 XBUS_INFO(xbus,
654                         "    CARD %d type=%d.%d ports=(%dx%d), "
655                         "port-dir=0x%02X\n",
656                         this_unit->addr.unit, this_unit->type,
657                         this_unit->subtype,
658                         this_unit->numchips, this_unit->ports_per_chip,
659                         this_unit->port_dir);
660                 spin_lock_irqsave(&worker->worker_lock, flags);
661                 worker->num_units++;
662                 XBUS_COUNTER(xbus, UNITS)++;
663                 list_add_tail(&card_desc->card_list, &worker->card_list);
664                 spin_unlock_irqrestore(&worker->worker_lock, flags);
665         }
666         CALL_PROTO(GLOBAL, RESET_SPI, xbus, NULL);
667         if (!xbus_process_worker(xbus)) {
668                 ret = -ENODEV;
669                 goto out;
670         }
671         goto out;
672 proto_err:
673         xbus_setstate(xbus, XBUS_STATE_FAIL);
674         dump_packet("AB_DESCRIPTION", pack, DBG_ANY);
675 out:
676         return ret;
677 }
678
679 HANDLER_DEF(GLOBAL, REGISTER_REPLY)
680 {
681         reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
682
683         if (!xpd) {
684                 static int rate_limit;
685
686                 if ((rate_limit++ % 1003) < 5)
687                         notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "");
688                 return -EPROTO;
689         }
690         if (debug & DBG_REGS) {
691                 dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum,
692                              reg);
693                 dump_packet("REG_REPLY", pack, 1);
694         }
695         if (!XMETHOD(card_register_reply, xpd)) {
696                 XPD_ERR(xpd,
697                         "REGISTER_REPLY: missing card_register_reply()\n");
698                 return -EINVAL;
699         }
700         return CALL_XMETHOD(card_register_reply, xpd, reg);
701 }
702
703 HANDLER_DEF(GLOBAL, SYNC_REPLY)
704 {
705         __u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
706         __u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
707         const char *mode_name;
708
709         BUG_ON(!xbus);
710         if ((mode_name = sync_mode_name(mode)) == NULL) {
711                 XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode);
712                 return -EINVAL;
713         }
714         XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift);
715         //dump_packet("SYNC_REPLY", pack, debug & DBG_SYNC);
716         got_new_syncer(xbus, mode, drift);
717         return 0;
718 }
719
720 #define TMP_NAME_LEN    (XBUS_NAMELEN + XPD_NAMELEN + 5)
721
722 HANDLER_DEF(GLOBAL, ERROR_CODE)
723 {
724         char tmp_name[TMP_NAME_LEN];
725         static long rate_limit;
726         __u8 category_code;
727         __u8 errorbits;
728
729         BUG_ON(!xbus);
730         if ((rate_limit++ % 5003) > 200)
731                 return 0;
732         category_code = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, category_code);
733         errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits);
734         if (!xpd) {
735                 snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
736                          XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
737         } else {
738                 snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname,
739                          xpd->xpdname);
740         }
741         NOTICE
742             ("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
743              tmp_name, cmd->name, category_code, errorbits, rate_limit);
744         dump_packet("FIRMWARE: ", pack, 1);
745         /*
746          * FIXME: Should implement an error recovery plan
747          */
748         return 0;
749 }
750
751 xproto_table_t PROTO_TABLE(GLOBAL) = {
752         .entries = {
753                 /*      Prototable      Card    Opcode          */
754                 XENTRY( GLOBAL,         GLOBAL, NULL_REPLY      ),
755                 XENTRY( GLOBAL,         GLOBAL, AB_DESCRIPTION  ),
756                 XENTRY( GLOBAL,         GLOBAL, SYNC_REPLY      ),
757                 XENTRY( GLOBAL,         GLOBAL, ERROR_CODE      ),
758                 XENTRY( GLOBAL,         GLOBAL, REGISTER_REPLY  ),
759         },
760         .name = "GLOBAL",
761         .packet_is_valid = global_packet_is_valid,
762         .packet_dump = global_packet_dump,
763 };
764
765 static bool global_packet_is_valid(xpacket_t *pack)
766 {
767         const xproto_entry_t *xe;
768
769         //DBG(GENERAL, "\n");
770         xe = xproto_global_entry(XPACKET_OP(pack));
771         return xe != NULL;
772 }
773
774 static void global_packet_dump(const char *msg, xpacket_t *pack)
775 {
776         DBG(GENERAL, "%s\n", msg);
777 }
778
779 #define MAX_PATH_STR    128
780
781 #ifndef UMH_WAIT_PROC
782 /*
783  * - UMH_WAIT_PROC was introduced as enum in 2.6.23
784  *   with a value of 1
785  * - It was changed to a macro (and it's value was modified) in 3.3.0
786  */
787 #define UMH_WAIT_PROC   1
788 #endif
789
790 int run_initialize_registers(xpd_t *xpd)
791 {
792         int ret;
793         xbus_t *xbus;
794         char busstr[MAX_ENV_STR];
795         char busnumstr[MAX_ENV_STR];
796         char modelstr[MAX_ENV_STR];
797         char unitstr[MAX_ENV_STR];
798         char subunitsstr[MAX_ENV_STR];
799         char typestr[MAX_ENV_STR];
800         char directionstr[MAX_ENV_STR];
801         char revstr[MAX_ENV_STR];
802         char connectorstr[MAX_ENV_STR];
803         char xbuslabel[MAX_ENV_STR];
804         char init_card[MAX_PATH_STR];
805         __u8 direction_mask;
806         __u8 hw_type = XPD_HW(xpd).type;
807         int i;
808         char *argv[] = {
809                 init_card,
810                 NULL
811         };
812         char *envp[] = {
813                 busstr,
814                 busnumstr,
815                 modelstr,
816                 unitstr,
817                 subunitsstr,
818                 typestr,
819                 directionstr,
820                 revstr,
821                 connectorstr,
822                 xbuslabel,
823                 NULL
824         };
825
826         BUG_ON(!xpd);
827         xbus = xpd->xbus;
828         if (!initdir || !initdir[0]) {
829                 XPD_NOTICE(xpd, "Missing initdir parameter\n");
830                 ret = -EINVAL;
831                 goto err;
832         }
833         if (!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
834                 ret = -EINVAL;
835                 goto err;
836         }
837         direction_mask = 0;
838         for (i = 0; i < xpd->subunits; i++) {
839                 xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
840
841                 if (!su) {
842                         XPD_ERR(xpd, "Have %d subunits, but not subunit #%d\n",
843                                 xpd->subunits, i);
844                         continue;
845                 }
846                 direction_mask |=
847                     (PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
848         }
849         snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname);
850         snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
851         snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
852                  xbus->transport.model_string);
853         snprintf(typestr, MAX_ENV_STR, "HW_TYPE=%d", hw_type);
854         snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
855         snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->xpd_type);
856         snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
857         snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
858                  direction_mask);
859         snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision);
860         snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s",
861                  xbus->connector);
862         snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
863         if (snprintf
864             (init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, hw_type,
865              xbus->revision) > MAX_PATH_STR) {
866                 XPD_NOTICE(xpd,
867                         "Cannot initialize. pathname is longer "
868                         "than %d characters.\n",
869                         MAX_PATH_STR);
870                 ret = -E2BIG;
871                 goto err;
872         }
873         if (!XBUS_IS(xbus, RECVD_DESC)) {
874                 XBUS_ERR(xbus,
875                          "Skipped register initialization. In state %s.\n",
876                          xbus_statename(XBUS_STATE(xbus)));
877                 ret = -ENODEV;
878                 goto err;
879         }
880         XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
881                 init_card, xpd->xpd_type, xbus->revision);
882         ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
883         /*
884          * Carefully report results
885          */
886         if (ret == 0)
887                 XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card);
888         else if (ret < 0) {
889                 XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card,
890                         ret);
891         } else {
892                 __u8 exitval = ((unsigned)ret >> 8) & 0xFF;
893                 __u8 sigval = ret & 0xFF;
894
895                 if (!exitval) {
896                         XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card,
897                                 sigval);
898                 } else {
899                         XPD_ERR(xpd, "'%s' aborted with exitval %d\n",
900                                 init_card, exitval);
901                 }
902                 ret = -EINVAL;
903         }
904 err:
905         return ret;
906 }
907 EXPORT_SYMBOL(run_initialize_registers);