This source file includes following definitions.
- ultrastor_14f_detect
- ultrastor_14f_info
- ultrastor_14f_queuecommand
- ultrastor_14f_command
- ultrastor_14f_abort
- ultrastor_14f_reset
- ultrastor_interrupt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <linux/config.h>
37
38 #ifdef CONFIG_SCSI_ULTRASTOR
39
40 #include <linux/stddef.h>
41 #include <linux/string.h>
42 #include <linux/sched.h>
43 #include <linux/kernel.h>
44
45 #include <asm/io.h>
46 #include <asm/system.h>
47
48 #define ULTRASTOR_PRIVATE
49 #include "ultrastor.h"
50 #include "scsi.h"
51 #include "hosts.h"
52
53 #define VERSION "1.0 beta"
54
55 #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
56 #define BIT(n) (1ul << (n))
57 #define BYTE(num, n) ((unsigned char)((unsigned int)(num) >> ((n) * 8)))
58
59
60
61
62 typedef struct {
63 unsigned char bytes[4];
64 } Longword;
65
66
67
68 struct config_1 {
69 unsigned char bios_segment: 3;
70 unsigned char reserved: 1;
71 unsigned char interrupt: 2;
72 unsigned char dma_channel: 2;
73 };
74 struct config_2 {
75 unsigned char ha_scsi_id: 3;
76 unsigned char mapping_mode: 2;
77 unsigned char bios_drive_number: 1;
78 unsigned char tfr_port: 2;
79 };
80
81
82
83 struct config {
84 unsigned short port_address;
85 const void *bios_segment;
86 unsigned char interrupt: 4;
87 unsigned char dma_channel: 3;
88 unsigned char ha_scsi_id: 3;
89 unsigned char heads: 6;
90 unsigned char sectors: 6;
91 unsigned char bios_drive_number: 1;
92 };
93
94
95
96 struct mscp {
97 unsigned char opcode: 3;
98 unsigned char xdir: 2;
99 unsigned char dcn: 1;
100 unsigned char ca: 1;
101 unsigned char sg: 1;
102 unsigned char target_id: 3;
103 unsigned char ch_no: 2;
104 unsigned char lun: 3;
105 Longword transfer_data;
106 Longword transfer_data_length;
107 Longword command_link;
108 unsigned char scsi_command_link_id;
109 unsigned char number_of_sg_list;
110 unsigned char length_of_sense_byte;
111 unsigned char length_of_scsi_cdbs;
112 unsigned char scsi_cdbs[12];
113 unsigned char adapter_status;
114 unsigned char target_status;
115 Longword sense_data;
116 };
117
118
119 static const void *const bios_segment_table[8] = {
120 NULL, (void *)0xC4000, (void *)0xC8000, (void *)0xCC000,
121 (void *)0xD0000, (void *)0xD4000, (void *)0xD8000, (void *)0xDC000,
122 };
123
124
125 static const unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
126
127
128 static const unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
129
130
131 static const struct {
132 unsigned char heads;
133 unsigned char sectors;
134 } mapping_table[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 0, 0 } };
135
136
137 static struct config config;
138
139
140 static int host_number;
141
142
143 #ifdef PORT_OVERRIDE
144 # define PORT_ADDRESS PORT_OVERRIDE
145 #else
146 # define PORT_ADDRESS (config.port_address)
147 #endif
148
149 static volatile int aborted = 0;
150
151 #ifndef PORT_OVERRIDE
152 static const unsigned short ultrastor_ports[] = {
153 0x330, 0x340, 0x310, 0x230, 0x240, 0x210, 0x130, 0x140,
154 };
155 #endif
156
157 static void ultrastor_interrupt(int cpl);
158
159 static void (*ultrastor_done)(int, int) = 0;
160
161 static const struct {
162 const char *signature;
163 size_t offset;
164 size_t length;
165 } signatures[] = {
166 { "SBIOS 1.01 COPYRIGHT (C) UltraStor Corporation,1990-1992.", 0x10, 57 },
167 };
168
169 int ultrastor_14f_detect(int hostnum)
170 {
171 size_t i;
172 unsigned char in_byte;
173 struct config_1 config_1;
174 struct config_2 config_2;
175
176 #if (ULTRASTOR_DEBUG & UD_DETECT)
177 printk("US14F: detect: called\n");
178 #endif
179
180 #ifndef PORT_OVERRIDE
181 PORT_ADDRESS = 0;
182 for (i = 0; i < ARRAY_SIZE(ultrastor_ports); i++) {
183 PORT_ADDRESS = ultrastor_ports[i];
184 #endif
185
186 #if (ULTRASTOR_DEBUG & UD_DETECT)
187 printk("US14F: detect: testing port address %03X\n", PORT_ADDRESS);
188 #endif
189
190 in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 0));
191 if (in_byte != US14F_PRODUCT_ID_0) {
192 #if (ULTRASTOR_DEBUG & UD_DETECT)
193 # ifdef PORT_OVERRIDE
194 printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);
195 # else
196 printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
197 # endif
198 #endif
199 #ifdef PORT_OVERRIDE
200 return FALSE;
201 #else
202 continue;
203 #endif
204 }
205 in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 1));
206
207 if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
208 #if (ULTRASTOR_DEBUG & UD_DETECT)
209 # ifdef PORT_OVERRIDE
210 printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);
211 # else
212 printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
213 # endif
214 #endif
215 #ifdef PORT_OVERRIDE
216 return FALSE;
217 #else
218 continue;
219 #endif
220 }
221 #ifndef PORT_OVERRIDE
222 break;
223 }
224 if (i == ARRAY_SIZE(ultrastor_ports)) {
225 # if (ULTRASTOR_DEBUG & UD_DETECT)
226 printk("US14F: detect: no port address found!\n");
227 # endif
228 return FALSE;
229 }
230 #endif
231
232 #if (ULTRASTOR_DEBUG & UD_DETECT)
233 printk("US14F: detect: adapter found at port address %03X\n",
234 PORT_ADDRESS);
235 #endif
236
237
238
239 *(char *)&config_1 = inb(CONFIG(PORT_ADDRESS + 0));
240 *(char *)&config_2 = inb(CONFIG(PORT_ADDRESS + 1));
241 config.bios_segment = bios_segment_table[config_1.bios_segment];
242 config.interrupt = interrupt_table[config_1.interrupt];
243 config.dma_channel = dma_channel_table[config_1.dma_channel];
244 config.ha_scsi_id = config_2.ha_scsi_id;
245 config.heads = mapping_table[config_2.mapping_mode].heads;
246 config.sectors = mapping_table[config_2.mapping_mode].sectors;
247 config.bios_drive_number = config_2.bios_drive_number;
248
249
250
251 if (config.bios_segment != NULL) {
252 int found = 0;
253
254 for (i = 0; !found && i < ARRAY_SIZE(signatures); i++)
255 if (memcmp((char *)config.bios_segment + signatures[i].offset,
256 signatures[i].signature, signatures[i].length))
257 found = 1;
258 if (!found)
259 config.bios_segment = NULL;
260 }
261 if (!config.bios_segment) {
262 #if (ULTRASTOR_DEBUG & UD_DETECT)
263 printk("US14F: detect: not detected.\n");
264 #endif
265 return FALSE;
266 }
267
268
269 if (!config.dma_channel || !(config_2.tfr_port & 0x2)) {
270 #if (ULTRASTOR_DEBUG & UD_DETECT)
271 printk("US14F: detect: consistancy check failed\n");
272 #endif
273 return FALSE;
274 }
275
276
277
278
279
280
281 #if (ULTRASTOR_DEBUG & UD_DETECT)
282 printk("US14F: detect: detect succeeded\n"
283 " Port address: %03X\n"
284 " BIOS segment: %05X\n"
285 " Interrupt: %u\n"
286 " DMA channel: %u\n"
287 " H/A SCSI ID: %u\n",
288 PORT_ADDRESS, config.bios_segment, config.interrupt,
289 config.dma_channel, config.ha_scsi_id);
290 #endif
291 host_number = hostnum;
292 scsi_hosts[hostnum].this_id = config.ha_scsi_id;
293 #ifndef NO_QUEUEING
294 {
295 struct sigaction sa;
296
297 sa.sa_handler = ultrastor_interrupt;
298 sa.sa_mask = 0;
299 sa.sa_flags = SA_INTERRUPT;
300 sa.sa_restorer = 0;
301 if (irqaction(config.interrupt, &sa)) {
302 printk("Unable to get IRQ%u for UltraStor controller\n",
303 config.interrupt);
304 return FALSE;
305 }
306 }
307 #endif
308 return TRUE;
309 }
310
311 const char *ultrastor_14f_info(void)
312 {
313 return "UltraStor 14F SCSI driver version "
314 VERSION
315 " by David B. Gentzel\n";
316 }
317
318 static struct mscp mscp = {
319 OP_SCSI, DTD_SCSI, 0, 1, 0
320 };
321
322 int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
323 void *buff, int bufflen, void (*done)(int, int))
324 {
325 unsigned char in_byte;
326
327 #if (ULTRASTOR_DEBUG & UD_COMMAND)
328 printk("US14F: queuecommand: called\n");
329 #endif
330
331
332 memset((char *)&mscp + 1, 0, sizeof (struct mscp) - 1);
333 mscp.target_id = target;
334
335 mscp.transfer_data = *(Longword *)&buff;
336 mscp.transfer_data_length = *(Longword *)&bufflen,
337 mscp.length_of_scsi_cdbs = ((*(unsigned char *)cmnd <= 0x1F) ? 6 : 10);
338 memcpy(mscp.scsi_cdbs, cmnd, mscp.length_of_scsi_cdbs);
339
340
341 do
342 in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
343 while (!aborted && (in_byte & 1));
344 if (aborted) {
345 #if (ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT))
346 printk("US14F: queuecommand: aborted\n");
347 #endif
348
349 return (aborted << 16);
350 }
351
352
353 outb_p(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
354 outb_p(BYTE(&mscp, 1), OGM_DATA_PTR(PORT_ADDRESS + 1));
355 outb_p(BYTE(&mscp, 2), OGM_DATA_PTR(PORT_ADDRESS + 2));
356 outb_p(BYTE(&mscp, 3), OGM_DATA_PTR(PORT_ADDRESS + 3));
357
358
359 outb_p(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
360
361 ultrastor_done = done;
362
363 #if (ULTRASTOR_DEBUG & UD_COMMAND)
364 printk("US14F: queuecommand: returning\n");
365 #endif
366
367 return 0;
368 }
369
370 #ifdef NO_QUEUEING
371 int ultrastor_14f_command(unsigned char target, const void *cmnd,
372 void *buff, int bufflen)
373 {
374 unsigned char in_byte;
375
376 #if (ULTRASTOR_DEBUG & UD_COMMAND)
377 printk("US14F: command: called\n");
378 #endif
379
380 (void)ultrastor_14f_queuecommand(target, cmnd, buff, bufflen, 0);
381
382
383 do
384 in_byte = inb_p(SYS_DOORBELL_INTR(PORT_ADDRESS));
385 while (!aborted && !(in_byte & 1));
386 if (aborted) {
387 #if (ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT))
388 printk("US14F: command: aborted\n");
389 #endif
390
391 return (aborted << 16);
392 }
393
394
395 outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
396
397 #if (ULTRASTOR_DEBUG & UD_COMMAND)
398 printk("US14F: command: returning %08X\n",
399 (mscp.adapter_status << 16) | mscp.target_status);
400 #endif
401
402
403 return (mscp.adapter_status << 16) | mscp.target_status;
404 }
405 #endif
406
407 int ultrastor_14f_abort(int code)
408 {
409 #if (ULTRASTOR_DEBUG & UD_ABORT)
410 printk("US14F: abort: called\n");
411 #endif
412
413 aborted = (code ? code : DID_ABORT);
414
415 #if (ULTRASTOR_DEBUG & UD_ABORT)
416 printk("US14F: abort: returning\n");
417 #endif
418
419 return 0;
420 }
421
422 int ultrastor_14f_reset(void)
423 {
424 unsigned char in_byte;
425
426 #if (ULTRASTOR_DEBUG & UD_RESET)
427 printk("US14F: reset: called\n");
428 #endif
429
430
431 outb_p(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS));
432
433
434 do
435 in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
436 while (in_byte & 0x20);
437
438 aborted = DID_RESET;
439
440 #if (ULTRASTOR_DEBUG & UD_RESET)
441 printk("US14F: reset: returning\n");
442 #endif
443 return 0;
444 }
445
446 #ifndef NO_QUEUEING
447 static void ultrastor_interrupt(int cpl)
448 {
449 #if (ULTRASTOR_DEBUG & UD_INTERRUPT)
450 printk("US14F: interrupt: called: status = %08X\n",
451 (mscp.adapter_status << 16) | mscp.target_status);
452 #endif
453
454 if (ultrastor_done == 0)
455 panic("US14F: interrupt: unexpected interrupt!\n");
456 else {
457 void (*done)(int, int);
458
459
460
461
462 done = ultrastor_done;
463 ultrastor_done = 0;
464
465
466 outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
467
468
469
470 done(host_number, (mscp.adapter_status << 16) | mscp.target_status);
471 }
472
473 #if (ULTRASTOR_DEBUG & UD_INTERRUPT)
474 printk("US14F: interrupt: returning\n");
475 #endif
476 }
477 #endif
478
479 #endif