FreeBSD/Linux Kernel Cross Reference
sys/i386ipsc/sd.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * Copyright 1988, 1989, 1990, 1991 by Intel Corporation,
28 * Santa Clara, California.
29 *
30 * All Rights Reserved
31 *
32 * Permission to use, copy, modify, and distribute this software and its
33 * documentation for any purpose and without fee is hereby granted,
34 * provided that the above copyright notice appears in all copies and that
35 * both the copyright notice and this permission notice appear in
36 * supporting documentation, and that the name of Intel not be used in
37 * advertising or publicity pertaining to distribution of the software
38 * without specific, written prior permission.
39 *
40 * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
41 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
42 * SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46 * THIS SOFTWARE.
47 */
48 /*
49 * HISTORY
50 * $Log: sd.c,v $
51 * Revision 2.8 93/01/14 17:32:17 danner
52 * Proper spl typing.
53 * [92/12/10 17:54:55 af]
54 *
55 * Revision 2.7 91/12/10 16:30:05 jsb
56 * Fixes from Intel
57 * [91/12/10 15:32:20 jsb]
58 *
59 * Revision 2.6 91/11/18 17:10:01 rvb
60 * Flush p_tag, and redo V_VALID computation like was done on
61 * all the other i386 disks.
62 *
63 * Revision 2.5 91/07/01 08:24:20 jsb
64 * Replaced first_sdopen_ever with sd_initialized.
65 * [91/06/29 16:09:42 jsb]
66 *
67 * Revision 2.4 91/06/18 20:50:32 jsb
68 * New copyright from Intel.
69 * [91/06/18 20:07:42 jsb]
70 *
71 * Revision 2.3 91/03/16 14:47:20 rpd
72 * Updated for new kmem_alloc interface.
73 * [91/03/03 rpd]
74 *
75 * Revision 2.2 90/12/04 14:47:41 jsb
76 * First checkin.
77 * [90/12/04 10:58:10 jsb]
78 *
79 */
80 /*
81 * sd.c Don Cameron August 1989
82 *
83 * This is the top half of the SCSI disk driver for MACH on the iPSC/2.
84 * The code is a rewrite of hd.c for MACH on the AT. Much code is also
85 * stolen from scsidrive.c from NX.
86 */
87
88 #include <sys/types.h>
89 #include <vm/vm_kern.h>
90 #ifdef MACH_KERNEL
91 #include <device/buf.h>
92 #include <device/errno.h>
93 #else MACH_KERNEL
94 #include <sys/ioctl.h>
95 #include <sys/types.h>
96 #include <sys/param.h>
97 #include <sys/buf.h>
98 #include <sys/errno.h>
99 #include <sys/user.h>
100 #include <sys/vmparam.h>
101 #include <sys/uio.h>
102 #include <mach/vm_param.h>
103 #endif MACH_KERNEL
104 #include <i386ipsc/scsi.h>
105 #include <i386at/disk.h>
106 #include <i386ipsc/sd.h>
107
108 /*
109 * Relative unit numbering allows each IO node to have drives which are
110 * virtually numbered from 0 even though the physical drives are not the
111 * first in the peripheral module - prp 6/28/90
112 */
113 #define UNITS_RELATIVE 1
114
115 #if UNITS_RELATIVE
116 #define RELUNIT(d) (UNIT(d) + first_unit)
117 #else UNITS_RELATIVE
118 #define RELUNIT(d) UNIT(d)
119 #endif UNITS_RELATIVE
120
121
122 #define PRIBIO 20
123 #ifndef NULL
124 #define NULL 0
125 #endif
126
127 /* Definitions for MAXTOR XT-8760s disks */
128 #define NSECPERTRACK 54
129 #define NCYLINDERS 1632
130 #define NHEADS 15
131
132 /* Hard coded values for partition info; this should be fixed */
133 #define PART0_START 0
134 #define PART0_SIZE 64800 /* 31.6 MB */
135
136 #define PART1_START (PART0_SIZE + PART0_START)
137 #define PART1_SIZE 103680 /* 53 MB */
138
139 #define PART2_START (PART1_SIZE + PART1_START)
140 #define PART2_SIZE 103680 /* 53 MB */
141
142 #define PART3_START (PART2_SIZE + PART2_START)
143 #define PART3_SIZE 103680 /* 53 MB */
144
145 #define PART4_START (PART3_SIZE + PART3_START)
146 #define PART4_SIZE 207360 /* 106 MB */
147
148 #define PART5_START (PART4_SIZE + PART4_START)
149 #define PART5_SIZE 207360 /* 106 MB */
150
151 /* From sys/systm.h */
152 struct buf *geteblk();
153
154 caddr_t scsiphys0;
155 caddr_t scsiphys1;
156 caddr_t scsiphys2;
157 caddr_t scsiphys3;
158
159 #define paddr(X) (paddr_t)(X->b_un.b_addr)
160
161 unsigned char curdrive = 0; /* drive we are using */
162
163 SCSI_INQUIRY inquiry; /* Result of inquiry command */
164 SCSI_SENSE sense; /* Result of sense command */
165
166 int scanning; /* In drive scan, timeouts OK */
167 int write_reserved; /* Write fifo lock variable */
168 extern int target_id; /* From sdintr.c */
169 extern int data_count; /* From sdintr.c */
170 extern int step; /* From sdintr.c */
171
172 struct hh hh[NDRIVES];
173 struct buf *bp1,
174 *bp2,
175 *bp3;
176
177 partition_t partition_struct[NDRIVES][V_NUMPAR];
178
179 typedef struct {
180 unsigned short ncylinders;
181 unsigned short nheads;
182 unsigned short nsecpertrack;
183 unsigned short present; /* Boolean: TRUE if unit exists */
184 unsigned short opened; /* Boolean: TRUE if any partition in
185 unit opened */
186 } sdisk_t;
187 sdisk_t sdparams[NDRIVES];
188
189 struct buf sdbuf[NDRIVES]; /* buffer for raw io */
190
191 #define DEBUG 0
192 #define dprintf if (DEBUG) printf
193
194 int sd_initialized = 0;
195 int sdstrategy();
196 int sdminphys();
197 int sdrawio();
198 caddr_t map_phys();
199
200 #if UNITS_RELATIVE
201 int first_unit;
202 #endif UNITS_RELATIVE
203
204 /* forward declarations */
205 static void sendcmd();
206
207 /* XXX dependency on old unixism */
208 MIN(x, y)
209 {
210 return (x < y ? x : y);
211 }
212
213 sdinit()
214 {
215 unsigned long n;
216 unsigned int x;
217
218 if (sd_initialized) {
219 return;
220 }
221 sd_initialized = 1;
222
223 #if UNITS_RELATIVE
224 first_unit = -1;
225 #endif UNITS_RELATIVE
226
227 printf("EXPERIMENTAL Mach iPSC/2 SCSI Disk Driver v1.0\n");
228
229 /*
230 * Map SCSI physical addresses into kernel virtual memory.
231 */
232 scsiphys0 = map_phys(SCSIPHYS0, SCSIPHYS0_LEN);
233 scsiphys1 = map_phys(SCSIPHYS1, SCSIPHYS1_LEN);
234 scsiphys2 = map_phys(SCSIPHYS2, SCSIPHYS2_LEN);
235 scsiphys3 = map_phys(SCSIPHYS3, SCSIPHYS3_LEN);
236
237 for (n = 0; n < NDRIVES; n++) {
238 hh[n].buflst.b_actf = hh[n].buflst.b_actl = NULL;
239 hh[n].buflst.b_active = 0;
240 sdparams[n].ncylinders = NCYLINDERS;
241 sdparams[n].nheads = NHEADS;
242 sdparams[n].nsecpertrack = NSECPERTRACK;
243 sdparams[n].opened = 0;
244 sdparams[n].present = 0;
245 }
246
247 /*
248 * Reset SCSI board and driver
249 */
250
251 reset_controller();
252
253 /*
254 * Reset SCSI bus
255 */
256
257 reset_bus();
258
259 /*
260 * Scan for drives. Set scanning flag so interrupt routine can
261 * special case errors.
262 */
263
264 scanning = 1;
265
266 for (n = 0; n < NDRIVES; n++) {
267
268 /*
269 * Send inquiry command
270 */
271 hh[n].cmd_busy = 1;
272 bzero(hh[n].cmd, 6);
273 hh[n].cmd_len = 6;
274 hh[n].cmd[0] = SCSI_INQUIRY_CMD;
275 hh[n].cmd[4] = sizeof(SCSI_INQUIRY);
276 hh[n].transfer_length = sizeof(SCSI_INQUIRY);
277 hh[n].rw_addr = (paddr_t)&inquiry;
278 hh[n].buf_io = 0;
279 hh[n].direction = 1;
280
281 /* Loop while drive busy in case it is still spinning up */
282 do {
283 sendcmd(n);
284 sleep(&hh[n].cmd_busy, PRIBIO);
285 } while (hh[n].cmd_st == CMD_ST_BUSY);
286
287 if (hh[n].cmd_st != CMD_ST_GOOD)
288 goto SCAN_NEXT;
289
290
291 /*
292 * Send request sense command
293 */
294
295 hh[n].cmd_busy = 1;
296 bzero(hh[n].cmd, 6);
297 hh[n].cmd_len = 6;
298 hh[n].cmd[0] = SCSI_SENSE_CMD;
299 hh[n].cmd[4] = sizeof(SCSI_SENSE);
300 hh[n].transfer_length = sizeof(SCSI_SENSE);
301 hh[n].rw_addr = (paddr_t)&sense;
302 hh[n].buf_io = 0;
303 hh[n].direction = 1;
304 sendcmd(n);
305 sleep(&hh[n].cmd_busy, PRIBIO);
306
307 if (hh[n].cmd_st != CMD_ST_GOOD)
308 goto SCAN_NEXT;
309
310 sdparams[n].present = 1;
311 #if UNITS_RELATIVE
312 if (first_unit < 0)
313 first_unit = n;
314 #endif UNITS_RELATIVE
315
316 SCAN_NEXT: ;
317 }
318 scanning = 0;
319
320 #if UNITS_RELATIVE
321 if (first_unit < 0)
322 first_unit = 0;
323 dprintf("First drive %d\n", first_unit);
324 #endif UNITS_RELATIVE
325 }
326
327
328 sdopen(dev, flags)
329 int dev;
330 int flags;
331 {
332 unsigned char unit, part, n;
333 int errcode = 0;
334 char c;
335
336 if (! sd_initialized) {
337 sdinit();
338 }
339
340 unit = RELUNIT(dev);
341 part = PARTITION(dev);
342 dprintf("sdopen: unit = 0x%x, partition = 0x%x\n", unit, part);
343
344 if (part >= V_NUMPAR || unit >= NDRIVES || !sdparams[unit].present) {
345 errcode = ENXIO;
346 dprintf("sdopen: bad unit or partition\n");
347 }
348 else {
349 if (!sdparams[unit].opened) {
350 getvtoc(unit);
351 sdparams[unit].opened = 1;
352 }
353 set_partition_info(unit);
354
355 #ifdef MACH_KERNEL
356 if (partition_struct[unit][part].p_flag & V_VALID ) {
357 partition_struct[unit][part].p_flag |= V_OPEN;
358 }
359 #else MACH_KERNEL
360 if (u.u_uid == 0) {
361 partition_struct[unit][part].p_flag |= V_OPEN;
362 }
363 else if (partition_struct[unit][part].p_flag & V_VALID ) {
364 partition_struct[unit][part].p_flag |= V_OPEN;
365 }
366 #endif MACH_KERNEL
367 else {
368 dprintf("sdopen: not valid or not uid 0\n");
369 errcode = ENXIO;
370 }
371 }
372
373 return(errcode);
374 }
375
376
377 sdclose(dev)
378 {
379 unsigned char unit, part;
380 unsigned int old_priority;
381
382 unit = RELUNIT(dev);
383 part = PARTITION(dev);
384 partition_struct[unit][part].p_flag &= ~V_OPEN;
385 }
386
387
388 #ifdef MACH_KERNEL
389 /*
390 * No need to limit IO size to 4096 bytes.
391 */
392 sdread(dev, ior)
393 dev_t dev;
394 io_req_t ior;
395 {
396 dprintf("sdread\n");
397 /*return(block_io(sdstrategy, sdminphys, ior));*/
398 return(block_io(sdstrategy, minphys, ior));
399 }
400
401 sdwrite(dev, ior)
402 dev_t dev;
403 io_req_t ior;
404 {
405 dprintf("sdwrite\n");
406 /*return(block_io(sdstrategy, sdminphys, ior));*/
407 return(block_io(sdstrategy, minphys, ior));
408 }
409
410 sdminphys(ior)
411 register io_req_t ior;
412 {
413 if (ior->io_count > PAGE_SIZE)
414 ior->io_count = PAGE_SIZE;
415 }
416
417 #else MACH_KERNEL
418 sdread(dev,uio)
419 register short dev;
420 struct uio *uio;
421 {
422 dprintf("sdread\n");
423 return(physio(sdstrategy, &sdbuf[RELUNIT(dev)], dev, B_READ, sdminphys, uio));
424 }
425
426 sdwrite(dev,uio)
427 dev_t dev;
428 struct uio *uio;
429 {
430 dprintf("sdwrite\n");
431 return(physio(sdstrategy, &sdbuf[RELUNIT(dev)], dev, B_WRITE, sdminphys, uio));
432 }
433
434 /* Trim buffer length if buffer-size is bigger than page size */
435 sdminphys(bp)
436 struct buf *bp;
437 {
438 if (bp->b_bcount > PAGE_SIZE)
439 bp->b_bcount = PAGE_SIZE;
440 }
441 #endif MACH_KERNEL
442
443 #ifdef MACH_KERNEL
444 #else MACH_KERNEL
445 sdioctl(dev, cmd, arg, mode)
446 dev_t dev;
447 int cmd;
448 caddr_t arg;
449 {
450 unsigned char unit, part;
451 union io_arg *arg_kernel;
452 unsigned int i, snum, old_priority;
453 struct absio *absio_kernel;
454 union vfy_io *vfy_io_kernel;
455 int xcount, errcode = 0;
456
457 unit = RELUNIT(dev);
458 part = PARTITION(dev);
459
460 switch (cmd) {
461 case V_CONFIG:
462 dprintf("sdioctl: V_CONFIG\n");
463 arg_kernel = (union io_arg *)arg;
464 if (arg_kernel->ia_cd.secsiz != SECSIZE) {
465 /* changing sector size NOT allowed */
466 errcode = EINVAL;
467 break;
468 }
469 sdparams[unit].ncylinders=(unsigned short)arg_kernel->ia_cd.ncyl;
470 sdparams[unit].nheads = (unsigned short)arg_kernel->ia_cd.nhead;
471 sdparams[unit].nsecpertrack = (unsigned short)arg_kernel->ia_cd.nsec;
472 reset_controller(unit);
473 break;
474
475 case V_REMOUNT:
476 dprintf("sdioctl: V_REMOUNT\n");
477 getvtoc(unit);
478 break;
479
480 case V_ADDBAD:
481 printf("SCSI disk driver: adding bad blocks not supported\n");
482 break;
483
484 case V_GETPARMS:
485 {
486 struct disk_parms *disk_parms = (struct disk_parms *)arg;
487
488 dprintf("sdioctl: V_GETPARAMS\n");
489 disk_parms->dp_type = DPT_WINI;
490 disk_parms->dp_heads = sdparams[unit].nheads;
491 disk_parms->dp_cyls = sdparams[unit].ncylinders;
492 disk_parms->dp_sectors = sdparams[unit].nsecpertrack;
493 disk_parms->dp_secsiz = SECSIZE;
494 disk_parms->dp_ptag = 0;
495 disk_parms->dp_pflag = partition_struct[unit][part].p_flag;
496 disk_parms->dp_pstartsec = partition_struct[unit][part].p_start;
497 disk_parms->dp_pnumsec =partition_struct[unit][part].p_size;
498 break;
499 }
500
501 case V_FORMAT:
502 dprintf("sdioctl: V_FORMAT\n");
503 /* All formatting arguments ignored */
504 format_command(unit);
505 break;
506
507 case V_PDLOC:
508 {
509 unsigned int *pd_loc;
510
511 dprintf("sdioctl: V_PDLOC\n");
512 pd_loc = (unsigned int *)arg;
513 *pd_loc = (unsigned int) PDLOCATION;
514 break;
515 }
516
517 case V_RDABS:
518 dprintf("sdioctl: V_RDABS\n");
519 /* V_RDABS is relative to head 0, sector 0, cylinder 0 */
520 if (u.u_uid != 0) {
521 errcode = ENXIO;
522 break;
523 }
524 bp1 = geteblk(SECSIZE);
525 absio_kernel = (struct absio *)arg;
526 bp1->b_flags = B_READ;
527
528 /* subtract partition offset as it will be added later by sdstart */
529 bp1->b_blkno = absio_kernel->abs_sec -
530 partition_struct[unit][0].p_start;
531
532 bp1->b_dev = unit << 4; /* 4 lsb's = 0 = partit 0 = RDABS */
533 bp1->b_bcount = SECSIZE;
534 sdstrategy(bp1);
535 biowait(bp1);
536 if (bp1->b_flags & B_ERROR) {
537 printf("SCSI disk driver: read failure on ioctl\n");
538 errcode = ENXIO;
539 brelse(bp1);
540 break;
541 }
542 if ( copyout( (caddr_t)paddr(bp1), absio_kernel->abs_buf,
543 SECSIZE) !=0 ) {
544 errcode = ENXIO;
545 }
546 brelse(bp1);
547 break;
548
549 case V_WRABS:
550
551 dprintf("sdioctl: V_WRABS\n");
552 /* V_WRABS is relative to head 0, sector 0, cylinder 0 */
553 if (u.u_uid != 0) {
554 errcode = ENXIO;
555 break;
556 }
557 bp1 = geteblk(SECSIZE);
558 absio_kernel = (struct absio *)arg;
559 if ( copyin( absio_kernel->abs_buf, (caddr_t)paddr(bp1),
560 SECSIZE) !=0 ) {
561 /* u.u_error =ENXIO; */
562 errcode = ENXIO;
563 brelse(bp1);
564 break;
565 }
566 bp1->b_flags = B_WRITE;
567
568 /* subtract partition offset as it will be added later by sdstart */
569 bp1->b_blkno = absio_kernel->abs_sec -
570 partition_struct[unit][0].p_start;
571
572 bp1->b_dev = unit << 4; /* 4 lsb's = 0 = partit 0 = RDABS */
573 bp1->b_bcount = SECSIZE;
574 sdstrategy(bp1);
575 biowait(bp1);
576 if (bp1->b_flags & B_ERROR) {
577 printf("SCSI disk driver: write failure on ioctl\n");
578 /* u.u_error =ENXIO; */
579 errcode = ENXIO;
580 }
581 brelse(bp1);
582 break;
583
584 case V_VERIFY:
585
586 dprintf("sdioctl: V_VERIFY\n");
587 if (u.u_uid != 0) {
588 errcode = ENXIO;
589 break;
590 }
591
592 bp1 = geteblk(PAGE_SIZE);
593 vfy_io_kernel = (union vfy_io *)arg;
594 bp1->b_flags = B_READ;
595 bp1->b_blkno = vfy_io_kernel->vfy_in.abs_sec;
596 bp1->b_dev = unit << 4; /* 4 lsb's = 0 = partit 0 = RDABS */
597 xcount = vfy_io_kernel->vfy_in.num_sec;
598 vfy_io_kernel->vfy_out.err_code = 0;
599 snum = PAGE_SIZE >> 9;
600 while (xcount > 0) {
601 i = (xcount > snum) ? snum : xcount;
602 bp1->b_bcount = i << 9;
603 sdstrategy(bp1);
604 biowait(bp1);
605 if (bp1->b_flags & B_ERROR) {
606 vfy_io_kernel->vfy_out.err_code = BAD_BLK;
607 break;
608 }
609 xcount -= i;
610 bp1->b_blkno += i;
611 bp1->b_flags &= ~B_DONE;
612 }
613 brelse(bp1);
614 break;
615
616 case V_XFORMAT:
617 printf("V_XFORMAT not supported\n");
618 break;
619
620 case FMTBAD:
621 printf("FMTBAD not supported\n");
622 break;
623
624 case GETALTTBL:
625 printf("GETALTTBL not supported\n");
626 break;
627
628 default:
629 printf("sdioctl(): do not recognize ioctl of 0x%x \n", cmd);
630 /* u.u_error = EINVAL; */
631 errcode = EINVAL;
632 }
633 }
634 #endif MACH_KERNEL
635
636 sdstrategy(bp)
637 struct buf *bp;
638 {
639 struct buf *ptr;
640 partition_t *partition_p;
641 unsigned char unit;
642 unsigned int track, direction;
643 spl_t old_priority;
644
645 unit = RELUNIT(bp->b_dev);
646 if (bp->b_bcount == 0) {
647 biodone(bp);
648 return;
649 }
650 partition_p= &(partition_struct[unit][PARTITION(bp->b_dev)]);
651
652 if ( !(partition_p->p_flag & V_VALID))
653 {
654 bp->b_flags = B_ERROR;
655 bp->b_error = ENXIO;
656 biodone(bp);
657 return;
658 }
659
660 /* if request is off the end or trying to write last block on out */
661
662 if ( (bp->b_blkno > partition_p->p_size) ||
663 (bp->b_blkno == partition_p->p_size & !(bp->b_flags & B_READ))) {
664 bp->b_flags = B_ERROR;
665 bp->b_error = ENXIO;
666 biodone(bp);
667 return;
668 }
669
670 if (bp->b_blkno == partition_p->p_size) {
671 /* indicate (read) EOF by setting b_resid to b_bcount on last block */
672 bp->b_resid = bp->b_bcount;
673 biodone(bp);
674 return;
675 }
676
677 /* since BSD does NOT have bp->b_cylin, use bp->b_resid */
678 bp->b_resid = (partition_p->p_start + bp->b_blkno) /
679 (sdparams[curdrive].nsecpertrack *
680 sdparams[curdrive].nheads);
681
682 old_priority = spl5();
683
684 disksort(&(hh[unit].buflst), bp);
685
686 if (!hh[unit].cmd_busy) {
687 sdstart();
688 }
689 splx(old_priority);
690 }
691
692
693 /* sdstart is called at spl5 */
694 sdstart()
695 {
696 int drivecount;
697 partition_t *partition_p;
698 struct hh *hh_p;
699 struct buf *bp;
700 int blocks;
701
702 for (drivecount = 0; drivecount < NDRIVES; drivecount++) {
703 if (curdrive < (NDRIVES - 1))
704 curdrive++;
705 else
706 curdrive = 0;
707 if ((bp = hh[curdrive].buflst.b_actf) != NULL)
708 break;
709 }
710 if (drivecount == NDRIVES)
711 return;
712
713 hh_p = &hh[curdrive];
714
715 partition_p = &partition_struct[RELUNIT(bp->b_dev)]
716 [PARTITION(bp->b_dev)];
717
718 /* see V_RDABS and V_WRABS in sdioctl() */
719 hh_p->physblock = partition_p->p_start + bp->b_blkno;
720 dprintf("sdstart: blkno = 0x%x pstart = 0x%x psize = 0x%x\n",
721 bp->b_blkno, partition_p->p_start, partition_p->p_size);
722 dprintf("sdstart: unit = 0x%x partition = 0x%x\n",
723 RELUNIT(bp->b_dev),PARTITION(bp->b_dev));
724
725 if (bp->b_bcount > PAGE_SIZE) {
726 dprintf("sdstart: big transfer\n");
727 }
728 hh_p->transfer_length = MIN(PAGE_SIZE, bp->b_bcount);
729 blocks = (hh_p->transfer_length + (SECSIZE-1)) >> 9;
730
731 if ((bp->b_blkno + blocks) > partition_p->p_size) {
732 printf("sdstart(): hit the end of the partition\n");
733 bp->b_bcount = (partition_p->p_size - bp->b_blkno) * SECSIZE;
734 hh_p->transfer_length = MIN(hh_p->transfer_length, bp->b_bcount);
735 blocks = (bp->b_bcount + (SECSIZE-1)) >> 9;
736 }
737
738 /* b_resid is set to the number of bytes to transfer */
739 bp->b_resid = bp->b_bcount;
740
741 hh_p->cmd_busy = 1;
742 hh_p->rw_addr = (paddr_t) bp->b_un.b_addr;
743 hh_p->buf_io = 1;
744 hh_p->retry_count = 0;
745 bzero(hh_p->cmd, 10);
746 hh_p->cmd_len = 10;
747 if (bp->b_flags & B_READ) {
748 hh_p->cmd[0] = SCSI_READ_CMD;
749 hh_p->direction = 1;
750 }
751 else {
752 hh_p->cmd[0] = SCSI_WRITE_CMD;
753 hh_p->direction = 0;
754 }
755 hh_p->cmd[2] = hh_p->physblock >> 24;
756 hh_p->cmd[3] = hh_p->physblock >> 16;
757 hh_p->cmd[4] = hh_p->physblock >> 8;
758 hh_p->cmd[5] = hh_p->physblock;
759 hh_p->cmd[8] = blocks;
760 dprintf("sdstart: blocks=0x%x transfer_length=0x%x physblock=0x%x direction=0x%x\n", blocks, hh_p->transfer_length, hh_p->physblock, hh_p->direction);
761 sendcmd(curdrive);
762 }
763
764 /*
765 * sdrestart is called at interrupt time to continue the transfer of
766 * a buffer that was greater than 4k. This occurs during the initial
767 * mount of root when ufs_mountroot tries to read an 8k block
768 */
769 sdrestart()
770 {
771 struct hh *hh_p;
772 struct buf *bp;
773 int blocks;
774
775 dprintf("sdrestart\n");
776 hh_p = &hh[curdrive];
777 bp = hh_p->buflst.b_actf;
778 hh_p->transfer_length = MIN(PAGE_SIZE, bp->b_resid);
779 blocks = (hh_p->transfer_length + (SECSIZE-1)) >> 9;
780 hh_p->physblock += PAGE_SIZE / SECSIZE;
781 hh_p->retry_count = 0;
782 hh_p->cmd[2] = hh_p->physblock >> 24;
783 hh_p->cmd[3] = hh_p->physblock >> 16;
784 hh_p->cmd[4] = hh_p->physblock >> 8;
785 hh_p->cmd[5] = hh_p->physblock;
786 hh_p->cmd[8] = blocks;
787 sendcmd(curdrive);
788 }
789
790
791 getvtoc(unit)
792 unsigned char unit;
793 {
794 unsigned char *c_p;
795 unsigned int dev;
796 unsigned int n, m;
797 char *pt1, *pt2;
798 struct boot_record *boot_record_p;
799 struct pdinfo *pd_p;
800 struct vtoc *vtoc_p;
801
802 /* make unit into a device of the form unit/partion 0
803 first four bits of device number are partition */
804 dev = unit << 4;
805 #if 0 /* ignore vtoc and pdinfo for now */
806 bp1 = geteblk(SECSIZE); /* for pdinfo */
807 bp2 = geteblk(SECSIZE); /* for vtoc */
808 #endif 0
809
810 /* make partition 0 the whole disk in case of failure */
811 partition_struct[unit][0].p_flag = V_OPEN|V_VALID;
812 partition_struct[unit][0].p_start = 0;
813 partition_struct[unit][0].p_size = sdparams[unit].ncylinders *
814 sdparams[unit].nheads * sdparams[unit].nsecpertrack;
815
816 #if 0 /* ignore vtoc and pdinfo for now */
817 /* get pdinfo */
818 bp1->b_flags = B_READ;
819 bp1->b_blkno = PDLOCATION;
820 bp1->b_dev = dev;
821 bp1->b_bcount = SECSIZE;
822 sdstrategy(bp1);
823 biowait(bp1);
824 if (bp1->b_flags & B_ERROR) {
825 printf("SCSI disk driver: can not read pdinfo on drive %d\n", unit);
826 return;
827 }
828 pd_p = (struct pdinfo *)bp1->b_un.b_addr;
829
830 if (pd_p->sanity != VALID_PD) {
831 printf("SCSI disk driver: pdinfo invalid on drive %d\n",unit);
832 return;
833 }
834 if (( pd_p->cyls != sdparams[unit].ncylinders) ||
835 ( pd_p->tracks != sdparams[unit].nheads) ||
836 ( pd_p->sectors != sdparams[unit].nsecpertrack))
837 printf("SCSI disk driver: pdinfo/setup mismatch on drive %d\n", unit);
838
839 if (pd_p->bytes != SECSIZE)
840 printf("SCSI disk driver: assuming sector size of %d on drive %d\n",SECSIZE, unit );
841
842 /* pd info from disk must be more accurate than hard coded values,
843 override sdparams and reset controller()
844 */
845 sdparams[unit].ncylinders = pd_p->cyls;
846 sdparams[unit].nheads = pd_p->tracks;
847 sdparams[unit].nsecpertrack = pd_p->sectors;
848 reset_controller(unit);
849
850
851 /* get vtoc */
852 bp2->b_flags = B_READ;
853 bp2->b_blkno = pd_p->vtoc_ptr/SECSIZE;
854 bp2->b_dev = dev;
855 bp2->b_bcount = SECSIZE;
856 sdstrategy(bp2);
857 biowait(bp2);
858 if (bp2->b_flags & B_ERROR) {
859 printf("SCSI disk driver: can not read vtoc on drive %d\n", unit);
860 return;
861 }
862 vtoc_p = (struct vtoc *)( bp2->b_un.b_addr +
863 (pd_p->vtoc_ptr % SECSIZE) );
864
865 if (vtoc_p->v_sanity != VTOC_SANE) {
866 printf("SCSI disk driver: vtoc corrupted on drive %d\n", unit);
867 return;
868 }
869
870 /* copy info on all valid partition, zero the others */
871
872 for (n = 0; n < vtoc_p->v_nparts; n++) {
873 /* this is a STRUCTURE copy */
874 partition_struct[unit][n] = vtoc_p->v_part[n];
875 if (vtoc_p->part[n].p_start >= 0 && vtoc_p->part[n].p_size >= 0)
876 partition_struct[unit][n].p_flag = V_VALID;
877 else
878 partition_struct[unit][n].p_flag = 0;
879 }
880 for ( ; n < V_NUMPAR; n++) {
881 partition_struct[unit][n].p_flag = 0;
882 partition_struct[unit][n].p_size = 0;
883 }
884 #endif 0
885 /* leave partition 0 "open" for raw I/O */
886 partition_struct[unit][0].p_flag |= V_OPEN;
887
888
889 #if 0
890 if (bp1 != NULL)
891 brelse(bp1);
892 if (bp2 != NULL)
893 brelse(bp2);
894 #endif 0
895 }
896
897 format_command(unit)
898 int unit; /* device to format */
899 {
900 printf("format_command() --not implemented\n");
901 }
902
903
904 start_rw(n, read)
905 int n; /* device index */
906 int read; /* Boolean: TRUE indicates read */
907 {
908 sendcmd(n);
909 }
910
911
912 dynamic_badblock()
913 {
914 printf("dynamic_badblock() --not implemented\n");
915 }
916
917 sdsize()
918 {
919 printf("sdsize() -- not implemented\n");
920 }
921
922 sddump()
923 {
924 printf("sddump() -- not implemented\n");
925 }
926
927
928 static void sendcmd(drive)
929 int drive;
930 {
931 int i;
932 spl_t old_priority;
933 struct hh *hh_p = &hh[drive];
934
935 if (hh_p->cmd[0] == SCSI_WRITE_CMD) {
936 write_reserved = 1;
937 }
938
939 old_priority = splhi();
940 while(target_id != -1)
941 sleep(&target_id, PRIBIO);
942 target_id = drive;
943 splx(old_priority);
944
945 data_count = 0;
946 step = CMD_STEP;
947 SCSI_ESP_FIFO = MSG_IDENTIFY;
948 shortdelay();
949 SCSI_ID = target_id;
950 for (i = 0; i < hh_p->cmd_len; i++) {
951 SCSI_ESP_FIFO = hh_p->cmd[i];
952 }
953 SCSI_COMMAND = ESP_SELATN;
954 }
955
956 /*
957 * map_phys: map physical SCSI addresses into kernel vm and return the
958 * (virtual) address.
959 */
960 caddr_t
961 map_phys(physaddr, length)
962 caddr_t physaddr; /* address to map */
963 int length; /* num bytes to map */
964 {
965 vm_offset_t vmaddr;
966 vm_offset_t pmap_addr;
967 vm_offset_t pmap_map_bd();
968
969 if (physaddr != (caddr_t)trunc_page(physaddr))
970 panic("map_phys: Tryed to map address not on page boundary");
971 if (kmem_alloc_pageable(kernel_map, &vmaddr, round_page(length))
972 != KERN_SUCCESS)
973 panic("map_phys: Can't allocate VM");
974 pmap_addr = pmap_map_bd(vmaddr, (vm_offset_t)physaddr,
975 (vm_offset_t)physaddr+length,
976 VM_PROT_READ | VM_PROT_WRITE);
977 return((caddr_t) vmaddr);
978 }
979
980 set_partition_info(unit)
981 unsigned int unit;
982 {
983 dprintf("set_partition_info\n");
984
985 partition_struct[unit][0].p_start = PART0_START;
986 partition_struct[unit][0].p_size = PART0_SIZE;
987 partition_struct[unit][0].p_flag = V_VALID;
988
989 partition_struct[unit][1].p_start = PART1_START;
990 partition_struct[unit][1].p_size = PART1_SIZE;
991 partition_struct[unit][1].p_flag = V_VALID;
992
993 partition_struct[unit][2].p_start = PART2_START;
994 partition_struct[unit][2].p_size = PART2_SIZE;
995 partition_struct[unit][2].p_flag = V_VALID;
996
997 partition_struct[unit][3].p_start = PART3_START;
998 partition_struct[unit][3].p_size = PART3_SIZE;
999 partition_struct[unit][3].p_flag = V_VALID;
1000
1001 partition_struct[unit][4].p_start = PART4_START;
1002 partition_struct[unit][4].p_size = PART4_SIZE;
1003 partition_struct[unit][4].p_flag = V_VALID;
1004
1005 partition_struct[unit][5].p_start = PART5_START;
1006 partition_struct[unit][5].p_size = PART5_SIZE;
1007 partition_struct[unit][5].p_flag = V_VALID;
1008 }
1009
Cache object: 03ac96b0d5b5fb56af78da80505f105a
|