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/dev/dpt/dpt_control.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  *       Copyright (c) 1997 by Simon Shapiro
    3  *       All Rights Reserved
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions, and the following disclaimer,
   10  *    without modification, immediately at the beginning of the file.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  */
   30 
   31 /**
   32  * dpt_control.c: Control Functions and /dev entry points for /dev/dpt*
   33  *
   34  * Caveat Emptor!       This is work in progress.       The interfaces and
   35  * functionality of this code will change (possibly radically) in the
   36  * future.
   37  */
   38 
   39 #ident "$FreeBSD: src/sys/dev/dpt/dpt_control.c,v 1.3.2.5 1999/09/05 08:09:11 peter Exp $"
   40 
   41 #include "opt_dpt.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/malloc.h>
   46 #include <sys/kernel.h>
   47 #include <sys/buf.h>
   48 #include <sys/uio.h>
   49 #include <sys/conf.h>
   50 #include <vm/vm.h>
   51 #include <vm/vm_kern.h>
   52 #include <vm/vm_extern.h>
   53 #include <vm/pmap.h>
   54 #include <scsi/scsiconf.h>
   55 
   56 #include <machine/cpu.h>
   57 
   58 #include <sys/dpt.h>
   59 
   60 #define INLINE __inline
   61 
   62 extern char     osrelease[];
   63 
   64 static dpt_sysinfo_t   dpt_sysinfo;
   65 
   66 /* Entry points and other prototypes */
   67 static vm_offset_t dpt_physmap(u_int32_t paddr, vm_size_t size);
   68 static void     dpt_unphysmap(u_int8_t * vaddr, vm_size_t size);
   69 
   70 static void     dpt_get_sysinfo(void);
   71 static INLINE dpt_softc_t *dpt_minor2softc(int minor_no);
   72 static INLINE int dpt_minor2unit(int minor_no);
   73 
   74 static int      dpt_open(dev_t dev, int flags, int fmt, struct proc * p);
   75 static int      dpt_close(dev_t dev, int flags, int fmt, struct proc * p);
   76 static int      dpt_write(dev_t dev, struct uio * uio, int ioflag);
   77 static int      dpt_read(dev_t dev, struct uio * uio, int ioflag);
   78 static int      dpt_ioctl(dev_t dev, int cmd, caddr_t cmdarg, int flags, struct proc * p);
   79 
   80 
   81 /* This has to be modified as the processor and CPU are not known yet */
   82 static dpt_sig_t dpt_sig = {
   83         'd', 'P', 't', 'S', 'i', 'G',
   84         SIG_VERSION, PROC_INTEL, PROC_386,
   85         FT_HBADRVR, FTF_PROTECTED,
   86         OEM_DPT, OS_FREEBSD,
   87         CAP_PASS | CAP_OVERLAP | CAP_RAID0 | CAP_RAID1 | CAP_RAID5 | CAP_ASPI,
   88         DEV_ALL, ADF_SC4_PCI | ADF_SC3_PCI, 0, 0,
   89         DPT_RELEASE, DPT_VERSION, DPT_PATCH,
   90         DPT_MONTH, DPT_DAY, DPT_YEAR,
   91         "DPT FreeBSD Driver (c) 1997 Simon Shapiro"
   92 };
   93 
   94 #define CDEV_MAJOR          DPT_CDEV_MAJOR
   95 
   96 /* Normally, this is a static structure.  But we need it in pci/dpt_pci.c */
   97 struct cdevsw   dpt_cdevsw = {
   98         dpt_open, dpt_close, dpt_read, dpt_write,
   99         dpt_ioctl, nostop, nullreset, nodevtotty,
  100         seltrue, nommap, NULL, "dpt",
  101 NULL, -1};
  102 
  103 static struct buf *dpt_inbuf[DPT_MAX_ADAPTERS];
  104 static char     dpt_rw_command[DPT_MAX_ADAPTERS][DPT_RW_CMD_LEN + 1];
  105 
  106 /**
  107  * Map a physical address to virtual one.
  108  * This is a first cut, experimental thing
  109  *
  110  * Paddr is the physical address to map
  111  * size is the size of the region, in bytes.
  112  * Because of alignment problems, we actually round up the size requested to
  113  * the next page count.
  114  */
  115 
  116 static          vm_offset_t
  117 dpt_physmap(u_int32_t req_paddr, vm_size_t req_size)
  118 {
  119         vm_offset_t     va;
  120         int             ndx;
  121         vm_size_t       size;
  122         u_int32_t       paddr;
  123         u_int32_t       offset;
  124 
  125 
  126 
  127         size = (req_size / PAGE_SIZE + 1) * PAGE_SIZE;
  128         paddr = req_paddr & 0xfffff000;
  129         offset = req_paddr - paddr;
  130 
  131         va = kmem_alloc_pageable(kernel_map, size);
  132         if (va == (vm_offset_t) 0)
  133                 return (va);
  134 
  135         for (ndx = 0; ndx < size; ndx += PAGE_SIZE) {
  136                 pmap_kenter(va + ndx, paddr + ndx);
  137                 invltlb();
  138         }
  139 
  140         return (va + offset);
  141 }
  142 
  143 
  144 /*
  145  * Release virtual space allocated by physmap We ASSUME that the correct
  146  * srart address and the correct LENGTH are given.
  147  * 
  148  * Disaster will follow if these assumptions are false!
  149  */
  150 
  151 static void
  152 dpt_unphysmap(u_int8_t * vaddr, vm_size_t size)
  153 {
  154         int             ndx;
  155 
  156         for (ndx = 0; ndx < size; ndx += PAGE_SIZE) {
  157                 pmap_kremove((vm_offset_t) vaddr + ndx);
  158         }
  159 
  160         kmem_free(kernel_map, (vm_offset_t) vaddr, size);
  161 }
  162 
  163 /**
  164  * Given a minor device number, get its SCSI Unit.
  165  */
  166 
  167 static INLINE int
  168 dpt_minor2unit(int minor)
  169 {
  170         int             unit;
  171 
  172         unit = minor2hba(minor & ~SCSI_CONTROL_MASK);
  173 
  174         return (unit);
  175 }
  176 
  177 /**
  178  * Given a minor device number,
  179  * return the pointer to its softc structure
  180  */
  181 
  182 static INLINE dpt_softc_t *
  183 dpt_minor2softc(int minor_no)
  184 {
  185         dpt_softc_t    *dpt;
  186 
  187         if (dpt_minor2unit(minor_no & ~SCSI_CONTROL_MASK) == -1)
  188                 return (NULL);
  189 
  190         for (dpt = TAILQ_FIRST(&dpt_softc_list);
  191              (dpt != NULL) && (dpt->unit != (minor_no & ~SCSI_CONTROL_MASK));
  192              dpt = TAILQ_NEXT(dpt, links));
  193 
  194         return (dpt);
  195 }
  196 
  197 /**
  198  * Collect interesting system information
  199  * The following is one of the worst hacks I have ever allowed my
  200  * name to be associated with.
  201  * There MUST be a system structure that provides this data.
  202  */
  203 
  204 static void
  205 dpt_get_sysinfo(void)
  206 {
  207         int             i;
  208         int             j;
  209         int             ospl;
  210         char           *addr;
  211 
  212         bzero(&dpt_sysinfo, sizeof(dpt_sysinfo_t));
  213 
  214         /**
  215          * This is really silly, but we better run this in splhigh as we
  216          * have no clue what we bump into.
  217          * Let's hope anyone else who does this sort of things protects them
  218          * with splhigh too.
  219          */
  220         ospl = splhigh();
  221 
  222         switch (cpu_class) {
  223         case CPUCLASS_386:
  224                 dpt_sig.Processor = dpt_sysinfo.processorType = PROC_386;
  225                 break;
  226         case CPUCLASS_486:
  227                 dpt_sig.Processor = dpt_sysinfo.processorType = PROC_486;
  228                 break;
  229         case CPUCLASS_586:
  230                 dpt_sig.Processor = dpt_sysinfo.processorType = PROC_PENTIUM;
  231                 break;
  232         case CPUCLASS_686:
  233                 dpt_sig.Processor = dpt_sysinfo.processorType = PROC_P6;
  234                 break;
  235         default:
  236                 dpt_sig.Processor = dpt_sysinfo.flags &= ~SI_ProcessorValid;
  237                 break;
  238         }
  239 
  240         /* Get The First Drive Type From CMOS */
  241         outb(0x70, 0x12);
  242         i = inb(0x71);
  243         j = i >> 4;
  244 
  245         if (i == 0x0f) {
  246                 outb(0x70, 0x19);
  247                 j = inb(0x71);
  248         }
  249         dpt_sysinfo.drive0CMOS = j;
  250 
  251         /* Get The Second Drive Type From CMOS */
  252         j = i & 0x0f;
  253         if (i == 0x0f) {
  254                 outb(0x70, 0x1a);
  255                 j = inb(0x71);
  256         }
  257         dpt_sysinfo.drive1CMOS = j;
  258 
  259         /* Get The Number Of Drives From The Bios Data Area */
  260         if ((addr = (char *) dpt_physmap(0x0475, 1024)) == NULL) {
  261                 printf("DPT:  Cannot map BIOS address 0x0475.  No sysinfo... :-(\n");
  262                 return;
  263         }
  264         dpt_sysinfo.numDrives = *addr;
  265         dpt_unphysmap(addr, 1024);
  266 
  267         /* Get the processor fields from the SIG structure, and set the flags */
  268         dpt_sysinfo.processorFamily = dpt_sig.ProcessorFamily;
  269         dpt_sysinfo.flags = SI_CMOS_Valid | SI_NumDrivesValid;
  270 
  271         /* Go out and look for SmartROM */
  272         for (i = 0; i < 3; ++i) {
  273                 switch (i) {
  274                 case 0:
  275                         addr = (char *) dpt_physmap(0xC8000, 1024);
  276                 case 1:
  277                         addr = (char *) dpt_physmap(0xD8000, 1024);
  278                 default:
  279                         addr = (char *) dpt_physmap(0xDC000, 1024);
  280                 }
  281 
  282                 if (addr == NULL)
  283                         continue;
  284 
  285                 if (*((u_int16_t *) addr) == 0xaa55) {
  286                         if ((*((u_int32_t *) (addr + 6)) == 0x00202053)
  287                           && (*((u_int32_t *) (addr + 10)) == 0x00545044)) {
  288                                 break;
  289                         }
  290                 }
  291                 dpt_unphysmap(addr, 1024);
  292                 addr = NULL;
  293         }
  294 
  295         /**
  296          * If i < 3, we founday it so set up a pointer to the starting
  297          * version digit by searching for it.
  298          */
  299         if (addr != NULL) {
  300                 addr += 0x15;
  301                 for (i = 0; i < 64; ++i)
  302                         if ((addr[i] == ' ') && (addr[i + 1] == 'v'))
  303                                 break;
  304                 if (i < 64) {
  305                         addr += (i + 4);
  306                 } else {
  307                         dpt_unphysmap(addr, 1024);
  308                         addr = NULL;
  309                 }
  310         }
  311         /* If all is well, set up the SmartROM version fields */
  312         if (addr != NULL) {
  313                 dpt_sysinfo.smartROMMajorVersion = *addr - ''; /* Assumes ASCII */
  314                 dpt_sysinfo.smartROMMinorVersion = *(addr + 2);
  315                 dpt_sysinfo.smartROMRevision = *(addr + 3);
  316                 dpt_sysinfo.flags |= SI_SmartROMverValid;
  317         } else {
  318                 dpt_sysinfo.flags |= SI_NO_SmartROM;
  319         }
  320 
  321         /* Get the conventional memory size from CMOS */
  322         outb(0x70, 0x16);
  323         j = inb(0x71);
  324         j <<= 8;
  325         outb(0x70, 0x15);
  326         j |= inb(0x71);
  327         dpt_sysinfo.conventionalMemSize = j;
  328 
  329         /**
  330          * Get the extended memory found at power on from CMOS
  331          */
  332         outb(0x70, 0x31);
  333         j = inb(0x71);
  334         j <<= 8;
  335         outb(0x70, 0x30);
  336         j |= inb(0x71);
  337         dpt_sysinfo.extendedMemSize = j;
  338         dpt_sysinfo.flags |= SI_MemorySizeValid;
  339 
  340         /* If there is 1 or 2 drives found, set up the drive parameters */
  341         if (dpt_sysinfo.numDrives > 0) {
  342                 /* Get the pointer from int 41 for the first drive parameters */
  343                 addr = (char *) dpt_physmap(0x0104, 1024);
  344 
  345                 if (addr != NULL) {
  346                         j = *((ushort *) (addr + 2));
  347                         j *= 16;
  348                         j += *((ushort *) (addr));
  349                         dpt_unphysmap(addr, 1024);
  350                         addr = (char *) dpt_physmap(j, 1024);
  351 
  352                         if (addr != NULL) {
  353                                 dpt_sysinfo.drives[0].cylinders = *((ushort *) addr);
  354                                 dpt_sysinfo.drives[0].heads = *(addr + 2);
  355                                 dpt_sysinfo.drives[0].sectors = *(addr + 14);
  356                                 dpt_unphysmap(addr, 1024);
  357                         }
  358                 }
  359                 if (dpt_sysinfo.numDrives > 1) {
  360                         /*
  361                          * Get the pointer from Int 46 for the second drive
  362                          * parameters
  363                          */
  364                         addr = (char *) dpt_physmap(0x01118, 1024);
  365                         j = *((ushort *) (addr + 2));
  366                         j *= 16;
  367                         j += *((ushort *) (addr));
  368                         dpt_unphysmap(addr, 1024);
  369                         addr = (char *) dpt_physmap(j, 1024);
  370 
  371                         if (addr != NULL) {
  372                                 dpt_sysinfo.drives[1].cylinders = *((ushort *) addr);
  373                                 dpt_sysinfo.drives[1].heads = *(addr + 2);
  374                                 dpt_sysinfo.drives[1].sectors = *(addr + 14);
  375                                 dpt_unphysmap(addr, 1024);
  376                         }
  377                 }
  378                 dpt_sysinfo.flags |= SI_DriveParamsValid;
  379         }
  380         splx(ospl);
  381 
  382         /* Get the processor information */
  383         dpt_sysinfo.flags |= SI_ProcessorValid;
  384 
  385         /* Get the bus I/O bus information */
  386         dpt_sysinfo.flags |= SI_BusTypeValid;
  387         dpt_sysinfo.busType = HBA_BUS_PCI;
  388 
  389 #warning "O/S Version determination is an ugly hack"
  390         dpt_sysinfo.osType = OS_FREEBSD;
  391         dpt_sysinfo.osMajorVersion = osrelease[0] - '';
  392         if (osrelease[1] == '.')
  393                 dpt_sysinfo.osMinorVersion = osrelease[2] - '';
  394         else
  395                 dpt_sysinfo.osMinorVersion = 0;
  396         if (osrelease[3] == '.')
  397                 dpt_sysinfo.osRevision = osrelease[4] - '';
  398         else
  399                 dpt_sysinfo.osMinorVersion = 0;
  400         if (osrelease[5] == '.')
  401                 dpt_sysinfo.osSubRevision = osrelease[6] - '';
  402         else
  403                 dpt_sysinfo.osMinorVersion = 0;
  404 
  405 
  406         dpt_sysinfo.flags |= SI_OSversionValid;
  407 }
  408 
  409 static int
  410 dpt_open(dev_t dev, int flags, int fmt, struct proc * p)
  411 {
  412         int             minor_no;
  413         int             ospl;
  414         dpt_softc_t    *dpt;
  415 
  416         minor_no = minor(dev);
  417 
  418         if (dpt_minor2unit(minor_no) == -1)
  419                 return (ENXIO);
  420         else
  421                 dpt = dpt_minor2softc(minor_no);
  422 
  423         if (dpt == NULL)
  424                 return (ENXIO);
  425 
  426         ospl = splbio();
  427 
  428         if (dpt->state & DPT_HA_CONTROL_ACTIVE) {
  429                 splx(ospl);
  430                 return (EBUSY);
  431         } else {
  432                 if ((dpt_inbuf[minor_no & ~SCSI_CONTROL_MASK] = geteblk(PAGE_SIZE))
  433                     == NULL) {
  434 #ifdef DPT_DEBUG_CONTROL
  435                         printf("dpt%d: Failed to obtain an I/O buffer\n",
  436                                minor_no & ~SCSI_CONTROL_MASK);
  437 #endif
  438                         return (EINVAL);
  439                 }
  440         }
  441 
  442         dpt->state |= DPT_HA_CONTROL_ACTIVE;
  443         splx(ospl);
  444         return (0);
  445 }
  446 
  447 static int
  448 dpt_close(dev_t dev, int flags, int fmt, struct proc * p)
  449 {
  450         int             minor_no;
  451         dpt_softc_t    *dpt;
  452 
  453         minor_no = minor(dev);
  454         dpt = dpt_minor2softc(minor_no);
  455 
  456         if ((dpt_minor2unit(minor_no) == -1) || (dpt == NULL))
  457                 return (ENXIO);
  458         else {
  459                 brelse(dpt_inbuf[minor_no & ~SCSI_CONTROL_MASK]);
  460                 dpt->state &= ~DPT_HA_CONTROL_ACTIVE;
  461                 return (0);
  462         }
  463 }
  464 
  465 static int
  466 dpt_write(dev_t dev, struct uio * uio, int ioflag)
  467 {
  468         int             minor_no;
  469         int             unit;
  470         int             error;
  471 
  472         minor_no = minor(dev);
  473 
  474         if (minor_no & SCSI_CONTROL_MASK) {
  475 #ifdef DPT_DEBUG_CONTROL
  476                 printf("dpt%d:  I/O attempted to control channel (%x)\n",
  477                        dpt_minor2unit(minor_no), minor_no);
  478 #endif
  479                 return (ENXIO);
  480         }
  481         unit = dpt_minor2unit(minor_no);
  482 
  483         if (unit == -1) {
  484                 return (ENXIO);
  485         } else if (uio->uio_resid > DPT_RW_CMD_LEN) {
  486                 return (E2BIG);
  487         } else {
  488                 char           *cp;
  489                 int             length;
  490 
  491                 cp = dpt_inbuf[minor_no]->b_data;
  492                 length = uio->uio_resid;        /* uiomove will change it! */
  493 
  494                 if ((error = uiomove(cp, length, uio) != 0)) {
  495 #ifdef DPT_DEBUG_CONTROL
  496                         printf("dpt%d: uiomove(%x, %d, %x) failed (%d)\n",
  497                                minor_no, cp, length, uio, error);
  498 #endif
  499                         return (error);
  500                 } else {
  501                         cp[length] = '\0';
  502 
  503                         /* A real kludge, to allow plain echo(1) to work */
  504                         if (cp[length - 1] == '\n')
  505                                 cp[length - 1] = '\0';
  506 
  507                         strncpy(dpt_rw_command[unit], cp, DPT_RW_CMD_LEN);
  508 #ifdef DPT_DEBUG_CONTROL
  509                         /**
  510                          * For lack of anything better to do;
  511                          * For now, dump the data so we can look at it and rejoice
  512                          */
  513                         printf("dpt%d: Command \"%s\" arrived\n",
  514                                unit, dpt_rw_command[unit]);
  515 #endif
  516                 }
  517         }
  518 
  519         return (error);
  520 }
  521 
  522 static int
  523 dpt_read(dev_t dev, struct uio * uio, int ioflag)
  524 {
  525         dpt_softc_t    *dpt;
  526         int             error;
  527         int             minor_no;
  528         int             ospl;
  529 
  530         minor_no = minor(dev);
  531         error = 0;
  532 
  533 #ifdef DPT_DEBUG_CONTROL
  534         printf("dpt%d: read, count = %d, dev = %08x\n",
  535                minor_no, uio->uio_resid, dev);
  536 #endif
  537 
  538         if (minor_no & SCSI_CONTROL_MASK) {
  539 #ifdef DPT_DEBUG_CONTROL
  540                 printf("dpt%d:  I/O attempted to control channel (%x)\n",
  541                        dpt_minor2unit(minor_no), minor_no);
  542 #endif
  543                 return (ENXIO);
  544         }
  545         if (dpt_minor2unit(minor_no) == -1) {
  546                 return (ENXIO);
  547         }
  548         /*
  549          * else if ( uio->uio_resid > PAGE_SIZE ) { return(E2BIG); }
  550          */ 
  551         else {
  552                 char           *work_buffer;
  553                 char           *wbp;
  554                 char           *command;
  555                 int             work_size;
  556                 int             ndx;
  557                 int             x;
  558 
  559                 if ((dpt = dpt_minor2softc(minor_no)) == NULL)
  560                         return (ENXIO);
  561 
  562                 work_buffer = (u_int8_t *) malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
  563                 wbp = work_buffer;
  564                 work_size = 0;
  565 
  566                 ospl = splbio();
  567 
  568                 command = dpt_rw_command[dpt->unit];
  569                 if (strcmp(command, DPT_RW_CMD_DUMP_SOFTC) == 0) {
  570                         x = sprintf(wbp, "dpt%d:%s:%s:%s:%s:%x\n",
  571                                     dpt->unit,
  572                                     dpt->board_data.vendor,
  573                                     dpt->board_data.modelNum,
  574                                     dpt->board_data.firmware,
  575                                     dpt->board_data.protocol,
  576                                     dpt->EATA_revision);
  577                         work_size += x;
  578                         wbp += x;
  579 
  580                 } else if (strcmp(command, DPT_RW_CMD_DUMP_SYSINFO) == 0) {
  581                         x = sprintf(wbp, "dpt%d:%d:%d:%d:%d:%d:%d:%d:%d:%s:"
  582                                     "%d:%d:%d:%d:%d:%d:%d:%d\n",
  583                                     dpt->unit,
  584                                     dpt_sysinfo.drive0CMOS,
  585                                     dpt_sysinfo.drive1CMOS,
  586                                     dpt_sysinfo.numDrives,
  587                                     dpt_sysinfo.processorFamily,
  588                                     dpt_sysinfo.processorType,
  589                                     dpt_sysinfo.smartROMMajorVersion,
  590                                     dpt_sysinfo.smartROMMinorVersion,
  591                                     dpt_sysinfo.smartROMRevision,
  592                                     i2bin(dpt_sysinfo.flags,
  593                                           sizeof(dpt->queue_status) * 8),
  594                                     dpt_sysinfo.conventionalMemSize,
  595                                     dpt_sysinfo.extendedMemSize,
  596                              dpt_sysinfo.osType, dpt_sysinfo.osMajorVersion,
  597                          dpt_sysinfo.osMinorVersion, dpt_sysinfo.osRevision,
  598                             dpt_sysinfo.osSubRevision, dpt_sysinfo.busType);
  599                         work_size += x;
  600                         wbp += x;
  601 
  602                         for (ndx = 0; ndx < 16; ndx++) {
  603                                 if (dpt_sysinfo.drives[ndx].cylinders != 0) {
  604                                         x = sprintf(wbp, "dpt%d:d%dc%dh%ds%d\n",
  605                                                     dpt->unit,
  606                                                     ndx,
  607                                           dpt_sysinfo.drives[ndx].cylinders,
  608                                               dpt_sysinfo.drives[ndx].heads,
  609                                            dpt_sysinfo.drives[ndx].sectors);
  610                                         work_size += x;
  611                                         wbp += x;
  612                                 }
  613                         }
  614                 } else if (strcmp(command, DPT_RW_CMD_DUMP_METRICS) == 0) {
  615                         x = sprintf(wbp,
  616                                     "dpt%d: No metrics available.\n"
  617                                     "Run the dpt_dm command, or use the\n"
  618                            "DPT_IOCTL_INTERNAL_METRICS ioctl system call\n",
  619                                     dpt->unit);
  620                         work_size += x;
  621                         wbp += x;
  622                 } else if (strcmp(command, DPT_RW_CMD_CLEAR_METRICS) == 0) {
  623 #ifdef DPT_MEASURE_PERFORMANCE
  624                         bzero(&dpt->performance, sizeof(dpt->performance));
  625 #endif                          /* DPT_MEASURE_PERFORMANCE */
  626 
  627                         x = sprintf(wbp, "dpt%d: Metrics have been cleared\n",
  628                                     dpt->unit);
  629                         work_size += x;
  630                         wbp += x;
  631                 } else if (strcmp(command, DPT_RW_CMD_SHOW_LED) == 0) {
  632 #ifdef DPT_MEASURE_PERFORMANCE
  633                         bzero(&dpt->performance, sizeof(dpt->performance));
  634 #endif                          /* DPT_MEASURE_PERFORMANCE */
  635 
  636                         x = sprintf(wbp, "dpt%d:%s\n",
  637                                 dpt->unit, i2bin(dpt_blinking_led(dpt), 8));
  638                         work_size += x;
  639                         wbp += x;
  640                 } else {
  641 #ifdef DPT_DEBUG_CONTROL
  642                         printf("dpt%d: Bad READ state (%s)\n", minor_no, command);
  643 #endif
  644                         splx(ospl);
  645                         error = EINVAL;
  646                 }
  647 
  648                 if (error == 0) {
  649                         work_buffer[work_size++] = '\0';
  650                         error = uiomove(work_buffer, work_size, uio);
  651                         uio->uio_resid = 0;
  652 #ifdef DPT_DEBUG_CONTROL
  653                         if (error) {
  654                                 printf("dpt%d: READ uimove failed (%d)\n", dpt->unit, error);
  655                         }
  656 #endif
  657                 }
  658         }
  659         splx(ospl);
  660         return (error);
  661 }
  662 
  663 /**
  664  * This is the control syscall interface.
  665  * It should be binary compatible with UnixWare,
  666  * if not totally syntatically so.
  667  */
  668 
  669 static int
  670 dpt_ioctl(dev_t dev, int cmd, caddr_t cmdarg, int flags, struct proc * p)
  671 {
  672         int             minor_no;
  673         dpt_softc_t    *dpt;
  674         dpt_user_softc_t udpt;
  675         int             result;
  676         int             ndx;
  677         eata_pt_t      *eata_pass_thru;
  678 
  679         minor_no = minor(dev);
  680         result = 0;
  681 
  682         if (!(minor_no & SCSI_CONTROL_MASK)) {
  683 #ifdef DPT_DEBUG_CONTROL
  684                 printf("dpt%d:  Control attempted to I/O channel (%x)\n",
  685                        dpt_minor2unit(minor_no), minor_no);
  686 #endif                          /* DEBUG */
  687                 return (ENXIO);
  688         } else
  689                 minor_no &= ~SCSI_CONTROL_MASK;
  690 
  691 #ifdef DPT_DEBUG_CONTROL
  692         printf("dpt%d: IOCTL(%x, %x, %p, %x, %p)\n",
  693                minor_no, dev, cmd, cmdarg, flags, p);
  694 #endif                          /* DEBUG */
  695 
  696         if ((dpt = dpt_minor2softc(minor_no)) == NULL)
  697                 return (result);
  698 
  699         switch (cmd) {
  700 #ifdef DPT_MEASURE_PERFORMANCE
  701         case DPT_IOCTL_INTERNAL_METRICS:
  702                 (void) memcpy(cmdarg, (char *) &dpt->performance, sizeof(dpt_perf_t));
  703                 return (0);
  704 #endif                          /* DPT_MEASURE_PERFORMANCE */
  705         case DPT_IOCTL_SOFTC:
  706                 udpt.unit = dpt->unit;
  707                 udpt.handle_interrupts = dpt->handle_interrupts;
  708                 udpt.target_mode_enabled = dpt->target_mode_enabled;
  709                 udpt.spare = dpt->spare;
  710 
  711                 udpt.total_ccbs_count = dpt->total_ccbs_count;
  712                 udpt.free_ccbs_count = dpt->free_ccbs_count;
  713                 udpt.waiting_ccbs_count = dpt->waiting_ccbs_count;
  714                 udpt.submitted_ccbs_count = dpt->submitted_ccbs_count;
  715                 udpt.completed_ccbs_count = dpt->completed_ccbs_count;
  716 
  717                 udpt.queue_status = dpt->queue_status;
  718                 udpt.free_lock = dpt->free_lock;
  719                 udpt.waiting_lock = dpt->waiting_lock;
  720                 udpt.submitted_lock = dpt->submitted_lock;
  721                 udpt.completed_lock = dpt->completed_lock;
  722 
  723                 udpt.commands_processed = dpt->commands_processed;
  724                 udpt.lost_interrupts = dpt->lost_interrupts;
  725 
  726                 udpt.channels = dpt->channels;
  727                 udpt.max_id = dpt->max_id;
  728                 udpt.max_lun = dpt->max_lun;
  729 
  730                 udpt.io_base = dpt->io_base;
  731                 udpt.v_membase = (u_int8_t *) dpt->v_membase;
  732                 udpt.p_membase = (u_int8_t *) dpt->p_membase;
  733 
  734                 udpt.irq = dpt->irq;
  735                 udpt.dma_channel = dpt->dma_channel;
  736 
  737                 udpt.board_data = dpt->board_data;
  738                 udpt.EATA_revision = dpt->EATA_revision;
  739                 udpt.bustype = dpt->bustype;
  740                 udpt.state = dpt->state;
  741 
  742                 udpt.primary = dpt->primary;
  743                 udpt.more_support = dpt->more_support;
  744                 udpt.immediate_support = dpt->immediate_support;
  745                 udpt.broken_INQUIRY = dpt->broken_INQUIRY;
  746                 udpt.spare2 = dpt->spare2;
  747 
  748                 for (ndx = 0; ndx < MAX_CHANNELS; ndx++) {
  749                         udpt.resetlevel[ndx] = dpt->resetlevel[ndx];
  750                         udpt.hostid[ndx] = dpt->hostid[ndx];
  751                 }
  752 
  753                 udpt.last_ccb = dpt->last_ccb;
  754                 udpt.cplen = dpt->cplen;
  755                 udpt.cppadlen = dpt->cppadlen;
  756                 udpt.queuesize = dpt->queuesize;
  757                 udpt.sgsize = dpt->sgsize;
  758                 udpt.cache_type = dpt->cache_type;
  759                 udpt.cache_size = dpt->cache_size;
  760 
  761                 (void) memcpy(cmdarg, (char *) &udpt, sizeof(dpt_user_softc_t));
  762                 return (0);
  763         case SDI_SEND:
  764         case DPT_IOCTL_SEND:
  765                 eata_pass_thru = (eata_pt_t *) cmdarg;
  766 
  767                 if ((eata_pass_thru->eataID[0] != 'E')
  768                     || (eata_pass_thru->eataID[1] != 'A')
  769                     || (eata_pass_thru->eataID[2] != 'T')
  770                     || (eata_pass_thru->eataID[3] != 'A')) {
  771                         return (EFAULT);
  772                 }
  773                 switch (eata_pass_thru->command) {
  774                 case DPT_SIGNATURE:
  775                         return (copyout((char *) &dpt_sig,
  776                                  (caddr_t *) eata_pass_thru->command_buffer,
  777                                         sizeof(dpt_sig)));
  778                 case DPT_NUMCTRLS:
  779                         return (copyout((char *) &dpt_controllers_present,
  780                                  (caddr_t *) eata_pass_thru->command_buffer,
  781                                         sizeof(dpt_controllers_present)));
  782                 case DPT_CTRLINFO:
  783                         {
  784                                 dpt_compat_ha_t compat_softc;
  785                                 int             ndx;
  786 
  787                                 compat_softc.ha_state = dpt->state;     /* Different Meaning! */
  788                                 for (ndx = 0; ndx < MAX_CHANNELS; ndx++)
  789                                         compat_softc.ha_id[ndx] = dpt->hostid[ndx];
  790 
  791                                 compat_softc.ha_vect = dpt->irq;
  792                                 compat_softc.ha_base = BaseRegister(dpt);
  793                                 compat_softc.ha_max_jobs = dpt->total_ccbs_count;
  794                                 compat_softc.ha_cache = dpt->cache_type;
  795                                 compat_softc.ha_cachesize = dpt->cache_size;
  796                                 compat_softc.ha_nbus = dpt->dma_channel + 1;
  797                                 compat_softc.ha_ntargets = dpt->max_id + 1;
  798                                 compat_softc.ha_nluns = dpt->max_lun + 1;
  799                                 compat_softc.ha_tshift = (dpt->max_id == 7) ? 3 : 4;
  800                                 compat_softc.ha_bshift = 2;
  801                                 compat_softc.ha_npend = dpt->submitted_ccbs_count;
  802                                 compat_softc.ha_active_jobs = dpt->waiting_ccbs_count;
  803                                 strncpy(compat_softc.ha_fw_version,
  804                                         dpt->board_data.firmware, 4);
  805                                 compat_softc.ha_ccb = NULL;
  806                                 compat_softc.ha_cblist = NULL;
  807                                 compat_softc.ha_dev = NULL;
  808                                 compat_softc.ha_StPkt_lock = NULL;
  809                                 compat_softc.ha_ccb_lock = NULL;
  810                                 compat_softc.ha_LuQWaiting = NULL;
  811                                 compat_softc.ha_QWait_lock = NULL;
  812                                 compat_softc.ha_QWait_opri = NULL;
  813 
  814                                 return (copyout((char *) &compat_softc,
  815                                  (caddr_t *) eata_pass_thru->command_buffer,
  816                                                 sizeof(dpt_compat_ha_t)));
  817                         }
  818                         break;
  819 
  820                 case DPT_SYSINFO:
  821                         return (copyout((char *) &dpt_sysinfo,
  822                                  (caddr_t *) eata_pass_thru->command_buffer,
  823                                         sizeof(dpt_sysinfo)));
  824                 case EATAUSRCMD:
  825                         printf("%d\n", __LINE__);
  826                         result = dpt_user_cmd(dpt, eata_pass_thru, cmdarg, minor_no);
  827                         printf("%d\n", __LINE__);
  828                         return (result);
  829                 case DPT_BLINKLED:
  830                         result = dpt_blinking_led(dpt);
  831                         return (copyout((caddr_t) & result,
  832                                  (caddr_t *) eata_pass_thru->command_buffer,
  833                                         sizeof(result)));
  834                 default:
  835                         printf("dpt%d: Invalid (%x) pass-throu command\n",
  836                                dpt->unit, eata_pass_thru->command);
  837                         result = EINVAL;
  838                 }
  839 
  840         default:
  841                 printf("dpt%d: Invalid (%x) IOCTL\n", dpt->unit, cmd);
  842                 return (EINVAL);
  843 
  844         }
  845 
  846         return (result);
  847 }
  848 
  849 static          dpt_devsw_installed = 0;
  850 
  851 static void
  852 dpt_drvinit(void *unused)
  853 {
  854         dev_t           dev;
  855 
  856         if (!dpt_devsw_installed) {
  857                 if (bootverbose)
  858                         printf("DPT:  RAID Manager driver, Version %d.%d.%d\n",
  859                                DPT_CTL_RELEASE, DPT_CTL_VERSION, DPT_CTL_PATCH);
  860 
  861                 /* Add the I/O (data) channel */
  862                 dev = makedev(CDEV_MAJOR, 0);
  863                 cdevsw_add(&dev, &dpt_cdevsw, NULL);
  864                 /* Add the Control (IOCTL) channel */
  865                 dev = makedev(CDEV_MAJOR, SCSI_CONTROL_MASK);
  866                 cdevsw_add(&dev, &dpt_cdevsw, NULL);
  867 
  868                 dpt_devsw_installed = 1;
  869         }
  870         dpt_get_sysinfo();
  871 }
  872 
  873 SYSINIT(dpt_dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, dpt_drvinit, NULL)
  874 /* End of the dpt_control driver */

Cache object: 66fcf5aa349caf81b1eeb6046033082d


[ 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.