The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386ipsc/sd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.