This source file includes following definitions.
- ultrastor_detect
- ultrastor_info
- build_sg_list
- ultrastor_queuecommand
- ultrastor_abort
- ultrastor_reset
- ultrastor_biosparam
- 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
37
38
39
40
41
42 #include <linux/stddef.h>
43 #include <linux/string.h>
44 #include <linux/sched.h>
45 #include <linux/kernel.h>
46 #include <linux/ioport.h>
47
48 #include <asm/io.h>
49 #include <asm/system.h>
50 #include <asm/dma.h>
51
52 #define ULTRASTOR_PRIVATE
53 #include "../blk.h"
54 #include "scsi.h"
55 #include "hosts.h"
56 #include "ultrastor.h"
57
58 #define ULTRASTOR_DEBUG 0
59
60 #define VERSION "1.1 alpha"
61
62 #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
63 #define BYTE(num, n) ((unsigned char)((unsigned int)(num) >> ((n) * 8)))
64
65
66
67
68 typedef struct {
69 unsigned char bytes[4];
70 } Longword;
71
72
73
74 struct config_1 {
75 unsigned char bios_segment: 3;
76 unsigned char removable_disks_as_fixed: 1;
77 unsigned char interrupt: 2;
78 unsigned char dma_channel: 2;
79 };
80 struct config_2 {
81 unsigned char ha_scsi_id: 3;
82 unsigned char mapping_mode: 2;
83 unsigned char bios_drive_number: 1;
84 unsigned char tfr_port: 2;
85 };
86
87
88
89 struct config {
90 const void *bios_segment;
91 unsigned short port_address;
92 unsigned char interrupt: 4;
93 unsigned char dma_channel: 3;
94 unsigned char bios_drive_number: 1;
95 unsigned char heads;
96 unsigned char sectors;
97 unsigned char ha_scsi_id: 3;
98 unsigned char subversion: 4;
99 };
100
101
102
103 struct mscp {
104 unsigned char opcode: 3;
105 unsigned char xdir: 2;
106 unsigned char dcn: 1;
107 unsigned char ca: 1;
108 unsigned char sg: 1;
109 unsigned char target_id: 3;
110 unsigned char ch_no: 2;
111 unsigned char lun: 3;
112 Longword transfer_data;
113 Longword transfer_data_length;
114 Longword command_link;
115 unsigned char scsi_command_link_id;
116 unsigned char number_of_sg_list;
117 unsigned char length_of_sense_byte;
118 unsigned char length_of_scsi_cdbs;
119 unsigned char scsi_cdbs[12];
120 unsigned char adapter_status;
121 unsigned char target_status;
122 Longword sense_data;
123 };
124
125
126 typedef struct {
127 unsigned long address;
128 unsigned long num_bytes;
129 } ultrastor_sg_list;
130
131
132 int mscp_free = TRUE;
133
134
135 static const void *const bios_segment_table_14f[8] = {
136 NULL, (void *)0xC4000, (void *)0xC8000, (void *)0xCC000,
137 (void *)0xD0000, (void *)0xD4000, (void *)0xD8000, (void *)0xDC000,
138 };
139
140
141 static const unsigned char interrupt_table_14f[4] = { 15, 14, 11, 10 };
142
143
144 static const unsigned char dma_channel_table_14f[4] = { 5, 6, 7, 0 };
145
146
147 static const struct {
148 unsigned char heads;
149 unsigned char sectors;
150 } mapping_table_14f[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 0, 0 } };
151
152
153 static const char *const subversion_names[] = { "14F", "34F" };
154
155
156 static struct config config;
157
158
159 static int host_number;
160
161
162 #ifdef PORT_OVERRIDE
163 # define PORT_ADDRESS PORT_OVERRIDE
164 #else
165 # define PORT_ADDRESS (config.port_address)
166 #endif
167
168 static volatile int aborted = 0;
169
170 #ifndef PORT_OVERRIDE
171
172 static const unsigned short ultrastor_ports_14f[] = {
173 0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140,
174 };
175 #endif
176
177 static void ultrastor_interrupt(int cpl);
178 static inline void build_sg_list(Scsi_Cmnd *SCpnt);
179
180 static void (*ultrastor_done)(Scsi_Cmnd *) = 0;
181 static Scsi_Cmnd *SCint = NULL;
182
183 int ultrastor_detect(int hostnum)
184 {
185 size_t i;
186 unsigned char in_byte, version_byte = 0;
187 struct config_1 config_1;
188 struct config_2 config_2;
189
190 #if (ULTRASTOR_DEBUG & UD_DETECT)
191 printk("US14F: detect: called\n");
192 #endif
193
194 #ifndef PORT_OVERRIDE
195 PORT_ADDRESS = 0;
196 for (i = 0; i < ARRAY_SIZE(ultrastor_ports_14f); i++) {
197 PORT_ADDRESS = ultrastor_ports_14f[i];
198 if(check_region(PORT_ADDRESS, 4)) continue;
199 #else
200 if(check_region(PORT_ADDRESS, 4)) {
201 printk("Ultrastor I/O space already in use\n");
202 return FALSE;
203 };
204 #endif
205
206 #if (ULTRASTOR_DEBUG & UD_DETECT)
207 printk("US14F: detect: testing port address %03X\n", PORT_ADDRESS);
208 #endif
209
210 in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 0));
211 if (in_byte != US14F_PRODUCT_ID_0) {
212 #if (ULTRASTOR_DEBUG & UD_DETECT)
213 # ifdef PORT_OVERRIDE
214 printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);
215 # else
216 printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
217 # endif
218 #endif
219 #ifdef PORT_OVERRIDE
220 return FALSE;
221 #else
222 continue;
223 #endif
224 }
225 in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 1));
226
227 if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
228 #if (ULTRASTOR_DEBUG & UD_DETECT)
229 # ifdef PORT_OVERRIDE
230 printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);
231 # else
232 printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
233 # endif
234 #endif
235 #ifdef PORT_OVERRIDE
236 return FALSE;
237 #else
238 continue;
239 #endif
240 }
241 version_byte = in_byte;
242 #ifndef PORT_OVERRIDE
243 break;
244 }
245 if (i == ARRAY_SIZE(ultrastor_ports_14f)) {
246 # if (ULTRASTOR_DEBUG & UD_DETECT)
247 printk("US14F: detect: no port address found!\n");
248 # endif
249 return FALSE;
250 }
251 #endif
252
253 #if (ULTRASTOR_DEBUG & UD_DETECT)
254 printk("US14F: detect: adapter found at port address %03X\n",
255 PORT_ADDRESS);
256 #endif
257
258 snarf_region(PORT_ADDRESS, 4);
259
260
261 *(char *)&config_1 = inb(CONFIG(PORT_ADDRESS + 0));
262 *(char *)&config_2 = inb(CONFIG(PORT_ADDRESS + 1));
263 config.bios_segment = bios_segment_table_14f[config_1.bios_segment];
264 config.interrupt = interrupt_table_14f[config_1.interrupt];
265 config.ha_scsi_id = config_2.ha_scsi_id;
266 config.heads = mapping_table_14f[config_2.mapping_mode].heads;
267 config.sectors = mapping_table_14f[config_2.mapping_mode].sectors;
268 config.bios_drive_number = config_2.bios_drive_number;
269 config.subversion = (version_byte & 0x0F);
270 if (config.subversion == U34F)
271 config.dma_channel = 0;
272 else
273 config.dma_channel = dma_channel_table_14f[config_1.dma_channel];
274
275 if (!config.bios_segment) {
276 #if (ULTRASTOR_DEBUG & UD_DETECT)
277 printk("US14F: detect: not detected.\n");
278 #endif
279 return FALSE;
280 }
281
282
283 if (config.subversion != U34F)
284 if (!config.dma_channel || !(config_2.tfr_port & 0x2)) {
285 #if (ULTRASTOR_DEBUG & UD_DETECT)
286 printk("US14F: detect: consistancy check failed\n");
287 #endif
288 return FALSE;
289 }
290
291
292
293
294
295
296 #if (ULTRASTOR_DEBUG & UD_DETECT)
297 printk("US14F: detect: detect succeeded\n"
298 " Port address: %03X\n"
299 " BIOS segment: %05X\n"
300 " Interrupt: %u\n"
301 " DMA channel: %u\n"
302 " H/A SCSI ID: %u\n"
303 " Subversion: %u\n",
304 PORT_ADDRESS, config.bios_segment, config.interrupt,
305 config.dma_channel, config.ha_scsi_id, config.subversion);
306 #endif
307 host_number = hostnum;
308 scsi_hosts[hostnum].this_id = config.ha_scsi_id;
309 scsi_hosts[hostnum].unchecked_isa_dma = (config.subversion != U34F);
310
311 if (request_irq(config.interrupt, ultrastor_interrupt)) {
312 printk("Unable to allocate IRQ%u for UltraStor controller.\n",
313 config.interrupt);
314 return FALSE;
315 }
316 if (config.dma_channel && request_dma(config.dma_channel)) {
317 printk("Unable to allocate DMA channel %u for UltraStor controller.\n",
318 config.dma_channel);
319 free_irq(config.interrupt);
320 return FALSE;
321 }
322 scsi_hosts[hostnum].sg_tablesize = ULTRASTOR_14F_MAX_SG;
323 printk("UltraStor: scatter/gather enabled. Using %d SG lists.\n", ULTRASTOR_14F_MAX_SG);
324
325 return TRUE;
326 }
327
328 const char *ultrastor_info(void)
329 {
330 static char buf[64];
331
332 (void)sprintf(buf, "UltraStor %s SCSI @ Port %03X BIOS %05X IRQ%u DMA%u\n",
333 ((config.subversion < ARRAY_SIZE(subversion_names))
334 ? subversion_names[config.subversion] : "14F?"),
335 PORT_ADDRESS, (int)config.bios_segment, config.interrupt,
336 config.dma_channel);
337 return buf;
338 }
339
340 static struct mscp mscp = {
341 OP_SCSI, DTD_SCSI, 0, 1, 0
342 };
343
344 static inline void build_sg_list(Scsi_Cmnd *SCpnt)
345 {
346 ultrastor_sg_list *sglist;
347 struct scatterlist *sl;
348 long transfer_length = 0;
349 int i;
350
351 sl = (struct scatterlist *) SCpnt->request_buffer;
352 SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);
353 if (SCpnt->host_scribble == NULL)
354
355 panic("US14F: Can't allocate DMA buffer for scatter-gather list!\n");
356
357 sglist = (ultrastor_sg_list *) SCpnt->host_scribble;
358 for (i = 0; i < SCpnt->use_sg; i++) {
359 sglist[i].address = (unsigned long) sl[i].address;
360 sglist[i].num_bytes = sl[i].length;
361 transfer_length += sl[i].length;
362 }
363 mscp.number_of_sg_list = (char) SCpnt->use_sg;
364 mscp.transfer_data = *(Longword *)&sglist;
365
366
367 mscp.transfer_data_length = *(Longword *)&transfer_length;
368 }
369
370 int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
371 {
372 unsigned char in_byte;
373
374 #if (ULTRASTOR_DEBUG & UD_COMMAND)
375 printk("US14F: queuecommand: called\n");
376 #endif
377
378
379
380
381
382
383 while (1) {
384 cli();
385 if (mscp_free) {
386 mscp_free = FALSE;
387 sti();
388 break;
389 }
390 sti();
391 }
392 mscp.opcode = OP_SCSI;
393 mscp.xdir = DTD_SCSI;
394 mscp.dcn = FALSE;
395
396
397
398
399
400
401
402 mscp.ca = scsi_devices[SCpnt->index].type != TYPE_TAPE;
403 mscp.target_id = SCpnt->target;
404 mscp.ch_no = 0;
405 mscp.lun = SCpnt->lun;
406 if (SCpnt->use_sg) {
407
408 mscp.sg = TRUE;
409 build_sg_list(SCpnt);
410 }
411 else {
412
413 mscp.sg = FALSE;
414 mscp.transfer_data = *(Longword *)&SCpnt->request_buffer;
415 mscp.transfer_data_length = *(Longword *)&SCpnt->request_bufflen;
416 SCpnt->host_scribble = NULL;
417 }
418 memset(&mscp.command_link, 0, sizeof(mscp.command_link));
419 mscp.scsi_command_link_id = 0;
420 mscp.length_of_sense_byte = 0;
421 mscp.length_of_scsi_cdbs = COMMAND_SIZE(*(unsigned char *)SCpnt->cmnd);
422 memcpy(mscp.scsi_cdbs, SCpnt->cmnd, mscp.length_of_scsi_cdbs);
423 mscp.adapter_status = 0;
424 mscp.target_status = 0;
425 memset(&mscp.sense_data, 0, sizeof(mscp.sense_data));
426
427
428 do
429 in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
430 while (!aborted && (in_byte & 1));
431 if (aborted) {
432 #if (ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT))
433 printk("US14F: queuecommand: aborted\n");
434 #endif
435
436 return (aborted << 16);
437 }
438
439
440 outb_p(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
441 outb_p(BYTE(&mscp, 1), OGM_DATA_PTR(PORT_ADDRESS + 1));
442 outb_p(BYTE(&mscp, 2), OGM_DATA_PTR(PORT_ADDRESS + 2));
443 outb_p(BYTE(&mscp, 3), OGM_DATA_PTR(PORT_ADDRESS + 3));
444
445
446 outb_p(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
447
448 ultrastor_done = done;
449 SCint = SCpnt;
450
451 #if (ULTRASTOR_DEBUG & UD_COMMAND)
452 printk("US14F: queuecommand: returning\n");
453 #endif
454
455 return 0;
456 }
457
458 int ultrastor_abort(Scsi_Cmnd *SCpnt, int code)
459 {
460 #if (ULTRASTOR_DEBUG & UD_ABORT)
461 printk("US14F: abort: called\n");
462 #endif
463
464 aborted = (code ? code : DID_ABORT);
465
466
467 if (SCpnt->host_scribble)
468 scsi_free(SCpnt->host_scribble, 512);
469
470
471 mscp_free = TRUE;
472
473 #if (ULTRASTOR_DEBUG & UD_ABORT)
474 printk("US14F: abort: returning\n");
475 #endif
476
477 return 0;
478 }
479
480 int ultrastor_reset(void)
481 {
482 #if 0
483 unsigned char in_byte;
484 #endif
485
486 #if (ULTRASTOR_DEBUG & UD_RESET)
487 printk("US14F: reset: called\n");
488 #endif
489
490
491 #if 0
492
493 outb_p(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS));
494
495
496 do
497 in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
498 while (in_byte & 0x20);
499
500 aborted = DID_RESET;
501 #endif
502
503 #if (ULTRASTOR_DEBUG & UD_RESET)
504 printk("US14F: reset: returning\n");
505 #endif
506 return 0;
507 }
508
509 int ultrastor_biosparam(int size, int dev, int *ip)
510 {
511 unsigned int s = config.heads * config.sectors;
512
513 ip[0] = config.heads;
514 ip[1] = config.sectors;
515 ip[2] = (size + (s - 1)) / s;
516
517
518 return 0;
519 }
520
521 static void ultrastor_interrupt(int cpl)
522 {
523 #if (ULTRASTOR_DEBUG & UD_INTERRUPT)
524 printk("US14F: interrupt: called: status = %08X\n",
525 (mscp.adapter_status << 16) | mscp.target_status);
526 #endif
527
528 if (ultrastor_done == 0)
529 panic("US14F: interrupt: unexpected interrupt");
530 else {
531 void (*done)(Scsi_Cmnd *);
532 Scsi_Cmnd *SCtmp;
533
534
535
536
537 done = ultrastor_done;
538 ultrastor_done = 0;
539 SCtmp = SCint;
540
541
542 outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
543
544
545
546 SCtmp->result = (mscp.adapter_status << 16) | mscp.target_status;
547
548
549 if (SCtmp->host_scribble)
550 scsi_free(SCtmp->host_scribble, 512);
551
552
553 mscp_free = TRUE;
554
555 done(SCtmp);
556 }
557
558 #if (ULTRASTOR_DEBUG & UD_INTERRUPT)
559 printk("US14F: interrupt: returning\n");
560 #endif
561 }