]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/hd/serial.c
Kleiner netter neuer Versuch.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / serial.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8
9 #include "hd.h"
10 #include "hd_int.h"
11 #include "serial.h"
12
13 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
14 * serial interface
15 *
16 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
17 */
18
19
20 static char *ser_names[] = {
21 "8250", "16450", "16550", "16650", "16750", "16850", "16950"
22 };
23
24 static void get_serial_info(hd_data_t *hd_data);
25 static serial_t *add_serial_entry(serial_t **ser, serial_t *new_ser);
26 static void dump_serial_data(hd_data_t *hd_data);
27
28 void hd_scan_serial(hd_data_t *hd_data)
29 {
30 hd_t *hd;
31 serial_t *ser, *next;
32 hd_res_t *res;
33 int i;
34 char buf[4], *skip_dev[16];
35 str_list_t *sl, *cmd;
36 unsigned skip_devs = 0;
37
38 if(!hd_probe_feature(hd_data, pr_serial)) return;
39
40 hd_data->module = mod_serial;
41
42 /* some clean-up */
43 remove_hd_entries(hd_data);
44 hd_data->serial = NULL;
45
46 PROGRESS(1, 0, "read info");
47
48 get_serial_info(hd_data);
49 if((hd_data->debug & HD_DEB_SERIAL)) dump_serial_data(hd_data);
50
51 for(i = 0; i < 2; i++) {
52 cmd = get_cmdline(hd_data, i == 0 ? "yast2ser" : "console");
53 for(sl = cmd; sl; sl = sl->next) {
54 if(sscanf(sl->str, "tty%3[^,]", buf) == 1) {
55 if(buf[1] == 0) {
56 switch(*buf) {
57 case 'a': strcpy(buf, "S0"); break;
58 case 'b': strcpy(buf, "S1"); break;
59 }
60 }
61 if(skip_devs < sizeof skip_dev / sizeof *skip_dev) {
62 skip_dev[skip_devs] = NULL;
63 str_printf(&skip_dev[skip_devs++], 0, "/dev/tty%s", buf);
64 }
65 }
66 }
67 free_str_list(cmd);
68 }
69
70 PROGRESS(2, 0, "build list");
71
72 for(ser = hd_data->serial; ser; ser = ser->next) {
73 hd = add_hd_entry(hd_data, __LINE__, 0);
74 hd->base_class.id = bc_comm;
75 hd->sub_class.id = sc_com_ser;
76 hd->prog_if.id = 0x80;
77 for(i = 0; (unsigned) i < sizeof ser_names / sizeof *ser_names; i++) {
78 if(strstr(ser->name, ser_names[i])) hd->prog_if.id = i;
79 }
80 hd->device.name = new_str(ser->name);
81 hd->func = ser->line;
82 str_printf(&hd->unix_dev_name, 0, "/dev/ttyS%u", ser->line);
83 for(i = 0; i < (int) skip_devs; i++) {
84 if(!strcmp(skip_dev[i], hd->unix_dev_name)) {
85 hd->tag.ser_skip = 1;
86 break;
87 }
88 }
89 if(ser->device) {
90 if(strstr(ser->device, "modem-printer")) {
91 hd->tag.ser_device = 1;
92 }
93 else if(strstr(ser->device, "infrared")) {
94 hd->tag.ser_device = 2;
95 }
96 else if(strstr(ser->device, "modem")) {
97 hd->tag.ser_device = 3;
98 }
99 }
100 if(ser->baud) {
101 res = add_res_entry(&hd->res, new_mem(sizeof *res));
102 res->baud.type = res_baud;
103 res->baud.speed = ser->baud;
104 }
105 res = add_res_entry(&hd->res, new_mem(sizeof *res));
106 res->io.type = res_io;
107 res->io.enabled = 1;
108 res->io.base = ser->port;
109 res->io.access = acc_rw;
110
111 res = add_res_entry(&hd->res, new_mem(sizeof *res));
112 res->irq.type = res_irq;
113 res->irq.enabled = 1;
114 res->irq.base = ser->irq;
115 }
116
117 for(ser = hd_data->serial; ser; ser = next) {
118 next = ser->next;
119
120 free_mem(ser->name);
121 free_mem(ser->device);
122 free_mem(ser);
123 }
124 hd_data->serial = NULL;
125
126 #if 0
127 if(hd_module_is_active(hd_data, "irda")) {
128 hd = add_hd_entry(hd_data, __LINE__, 0);
129 hd->base_class.id = bc_comm;
130 hd->sub_class.id = sc_com_ser;
131 hd->prog_if.id = 0x80;
132 hd->device.name = new_str("IrDA Serial");
133 hd->unix_dev_name = new_str("/dev/ircomm0");
134 }
135 #endif
136 }
137
138 void get_serial_info(hd_data_t *hd_data)
139 {
140 char buf[64];
141 unsigned u0, u1, u2;
142 #if !defined(__PPC__)
143 unsigned u3;
144 #endif
145 int i;
146 str_list_t *sl, *sl0;
147 serial_t *ser;
148
149 #if !defined(__PPC__)
150 /*
151 * Max. 44 serial lines at the moment; the serial proc interface is
152 * somewhat buggy at the moment (2.2.13), hence the explicit 44 lines
153 * limit. That may be dropped later.
154 */
155 sl0 = read_file(PROC_DRIVER_SERIAL, 1, 44);
156
157 // ########## FIX !!!!!!!! ########
158 if(sl0) {
159 for(sl = sl0; sl; sl = sl->next) {
160 i = 0;
161 if(
162 sscanf(sl->str, "%u: uart:%31s port:%x irq:%u baud:%u", &u0, buf, &u1, &u2, &u3) == 5 ||
163 (i = 1, sscanf(sl->str, "%u: uart:%31s port:%x irq:%u tx:%u", &u0, buf, &u1, &u2, &u3) == 5)
164 ) {
165 /*
166 * The 'baud' or 'tx' entries are only present for real interfaces.
167 */
168 ser = add_serial_entry(&hd_data->serial, new_mem(sizeof *ser));
169 ser->line = u0;
170 ser->port = u1;
171 ser->irq = u2;
172 if(!i) ser->baud = u3;
173 ser->name = new_str(buf);
174 }
175 }
176
177 if((hd_data->debug & HD_DEB_SERIAL)) {
178 /* log just the first 16 entries */
179 ADD2LOG("----- "PROC_DRIVER_SERIAL" -----\n");
180 for(sl = sl0, i = 16; sl && i--; sl = sl->next) {
181 ADD2LOG(" %s", sl->str);
182 }
183 ADD2LOG("----- "PROC_DRIVER_SERIAL" end -----\n");
184 }
185 }
186 #endif /* !defined(__PPC__) */
187
188 #if defined(__PPC__)
189 sl0 = read_file(PROC_DRIVER_MACSERIAL, 1, 0);
190
191 if(sl0) {
192 for(sl = sl0; sl; sl = sl->next) {
193 if(
194 (i = sscanf(sl->str, "%u: port:%x irq:%u con:%63[^\n]", &u0, &u1, &u2, buf)) >= 3
195 ) {
196 ser = add_serial_entry(&hd_data->serial, new_mem(sizeof *ser));
197 ser->line = u0;
198 ser->port = u1;
199 ser->irq = u2;
200 ser->name = new_str("SCC");
201 if(i == 4) ser->device = new_str(buf);
202 }
203 }
204
205 if((hd_data->debug & HD_DEB_SERIAL)) {
206 /* log just the first 16 entries */
207 ADD2LOG("----- "PROC_DRIVER_MACSERIAL" -----\n");
208 for(sl = sl0, i = 16; sl && i--; sl = sl->next) {
209 ADD2LOG(" %s", sl->str);
210 }
211 ADD2LOG("----- "PROC_DRIVER_MACSERIAL" end -----\n");
212 }
213 }
214 #endif /* defined(__PPC__) */
215
216
217 free_str_list(sl0);
218 }
219
220 serial_t *add_serial_entry(serial_t **ser, serial_t *new_ser)
221 {
222 while(*ser) ser = &(*ser)->next;
223 return *ser = new_ser;
224 }
225
226 void dump_serial_data(hd_data_t *hd_data)
227 {
228 serial_t *ser;
229
230 ADD2LOG("----- serial info -----\n");
231 for(ser = hd_data->serial; ser; ser = ser->next) {
232 ADD2LOG(
233 " uart %s, line %d, port 0x%03x, irq %d, baud %d\n",
234 ser->name, ser->line, ser->port, ser->irq, ser->baud
235 );
236 }
237 ADD2LOG("----- serial info end -----\n");
238 }
239