]>
Commit | Line | Data |
---|---|---|
a6316ce4 MT |
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 |