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