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/ips/ips.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) 2002 Adaptec Inc.
    3  * All rights reserved.
    4  *
    5  * Written by: David Jeffery
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD: releng/5.1/sys/dev/ips/ips.c 114902 2003-05-11 06:36:49Z scottl $
   29  */
   30 
   31 
   32 #include <dev/ips/ips.h>
   33 #include <sys/stat.h>
   34 #include <sys/time.h>
   35 #include <machine/clock.h>
   36 
   37 static d_open_t ips_open;
   38 static d_close_t ips_close;
   39 static d_ioctl_t ips_ioctl;
   40 
   41 #define IPS_CDEV_MAJOR 175
   42 static struct cdevsw ips_cdevsw = {
   43         .d_open = ips_open,
   44         .d_close = ips_close,
   45         .d_ioctl = ips_ioctl,
   46         .d_name = "ips",
   47         .d_maj = IPS_CDEV_MAJOR,
   48 };
   49 
   50 
   51 static int ips_open(dev_t dev, int flags, int fmt, struct thread *td)
   52 {
   53         ips_softc_t *sc = dev->si_drv1;
   54         sc->state |= IPS_DEV_OPEN;
   55         return 0;
   56 }
   57 
   58 static int ips_close(dev_t dev, int flags, int fmt, struct thread *td)
   59 {
   60         ips_softc_t *sc = dev->si_drv1;
   61         sc->state &= ~IPS_DEV_OPEN;
   62 
   63         return 0;
   64 }
   65 
   66 static int ips_ioctl(dev_t dev, u_long command, caddr_t addr, int32_t flags, struct thread *td)
   67 {
   68         ips_softc_t *sc;
   69 
   70         sc = dev->si_drv1;
   71         return ips_ioctl_request(sc, command, addr, flags);
   72 }
   73 
   74 static void ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
   75 {
   76         ips_command_t *command = cmdptr;
   77         PRINTF(10, "ips: in ips_cmd_dmaload\n");
   78         if(!error)
   79                 command->command_phys_addr = segments[0].ds_addr;
   80 
   81 }
   82 
   83 /* is locking needed? what locking guarentees are there on removal? */
   84 static __inline__ int ips_cmdqueue_free(ips_softc_t *sc)
   85 {
   86         int i, error = -1;
   87         intrmask_t mask = splbio();
   88         if(!sc->used_commands){
   89                 for(i = 0; i < sc->max_cmds; i++){
   90                         if(!(sc->commandarray[i].command_phys_addr))
   91                                 continue;
   92                         bus_dmamap_unload(sc->command_dmatag, 
   93                                           sc->commandarray[i].command_dmamap);
   94                         bus_dmamem_free(sc->command_dmatag, 
   95                                         sc->commandarray[i].command_buffer,
   96                                         sc->commandarray[i].command_dmamap);
   97                 }
   98                 error = 0;
   99                 sc->state |= IPS_OFFLINE;
  100         }
  101         splx(mask);
  102         return error;
  103 }
  104 
  105 /* places all ips command structs on the free command queue.  No locking as if someone else tries
  106  * to access this during init, we have bigger problems */
  107 static __inline__ int ips_cmdqueue_init(ips_softc_t *sc)
  108 {
  109         int i;
  110         ips_command_t *command;
  111         SLIST_INIT(&sc->free_cmd_list);
  112         STAILQ_INIT(&sc->cmd_wait_list);
  113         for(i = 0; i < sc->max_cmds; i++){
  114                 sc->commandarray[i].id = i;
  115                 sc->commandarray[i].sc = sc;
  116                 SLIST_INSERT_HEAD(&sc->free_cmd_list, &sc->commandarray[i], 
  117                                   next);        
  118         }
  119         for(i = 0; i < sc->max_cmds; i++){
  120                 command = &sc->commandarray[i];
  121                 if(bus_dmamem_alloc(sc->command_dmatag,&command->command_buffer,
  122                     BUS_DMA_NOWAIT, &command->command_dmamap))
  123                         goto error;
  124                 bus_dmamap_load(sc->command_dmatag, command->command_dmamap, 
  125                                 command->command_buffer,IPS_COMMAND_LEN, 
  126                                 ips_cmd_dmaload, command, BUS_DMA_NOWAIT);
  127                 if(!command->command_phys_addr){
  128                         bus_dmamem_free(sc->command_dmatag, 
  129                             command->command_buffer, command->command_dmamap);
  130                         goto error;
  131                 }
  132         }
  133         sc->state &= ~IPS_OFFLINE;
  134         return 0;
  135 error:
  136                 ips_cmdqueue_free(sc);
  137                 return ENOMEM;
  138 }
  139 
  140 static int ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags)
  141 {
  142         intrmask_t mask;
  143         ips_command_t *command;
  144         ips_wait_list_t *waiter;
  145         unsigned long memflags = 0;
  146         if(IPS_NOWAIT_FLAG & flags)
  147                 memflags = M_NOWAIT;
  148         waiter = malloc(sizeof(ips_wait_list_t), M_DEVBUF, memflags);
  149         if(!waiter)
  150                 return ENOMEM;
  151         mask = splbio();
  152         if(sc->state & IPS_OFFLINE){
  153                 splx(mask);
  154                 return EIO;
  155         }
  156         command = SLIST_FIRST(&sc->free_cmd_list);
  157         if(command && !(sc->state & IPS_TIMEOUT)){
  158                 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
  159                 (sc->used_commands)++;
  160                 splx(mask);
  161                 clear_ips_command(command);
  162                 bzero(command->command_buffer, IPS_COMMAND_LEN);
  163                 free(waiter, M_DEVBUF);
  164                 command->arg = data;
  165                 return callback(command);
  166         }
  167         DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n"); 
  168         waiter->callback = callback; 
  169         waiter->data = data;
  170         STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
  171         splx(mask);
  172         return 0;
  173 }
  174 
  175 static void ips_run_waiting_command(ips_softc_t *sc)
  176 {
  177         ips_wait_list_t *waiter;
  178         ips_command_t   *command;
  179         int (*callback)(ips_command_t*);
  180         intrmask_t mask;
  181 
  182         mask = splbio();
  183         waiter = STAILQ_FIRST(&sc->cmd_wait_list);
  184         command = SLIST_FIRST(&sc->free_cmd_list);
  185         if(!waiter || !command){
  186                 splx(mask);
  187                 return;
  188         }
  189         DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
  190         SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
  191         STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
  192         (sc->used_commands)++;
  193         splx(mask);
  194         clear_ips_command(command);
  195         bzero(command->command_buffer, IPS_COMMAND_LEN);
  196         command->arg = waiter->data;
  197         callback = waiter->callback;
  198         free(waiter, M_DEVBUF);
  199         callback(command);
  200         return; 
  201 }
  202 /* returns a free command struct if one is available. 
  203  * It also blanks out anything that may be a wild pointer/value.
  204  * Also, command buffers are not freed.  They are
  205  * small so they are saved and kept dmamapped and loaded.
  206  */
  207 int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags)
  208 {
  209         intrmask_t mask;
  210         ips_command_t *command;
  211         mask = splbio();
  212 
  213         if(sc->state & IPS_OFFLINE){
  214                 splx(mask);
  215                 return EIO;
  216         }
  217         command = SLIST_FIRST(&sc->free_cmd_list);
  218         if(!command || (sc->state & IPS_TIMEOUT)){
  219                 splx(mask);
  220                 if(flags & IPS_NOWAIT_FLAG)
  221                         return EAGAIN;
  222                 return ips_add_waiting_command(sc, callback, data, flags);
  223         }
  224         SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
  225         (sc->used_commands)++;
  226         splx(mask);
  227         clear_ips_command(command);
  228         bzero(command->command_buffer, IPS_COMMAND_LEN);
  229         command->arg = data;
  230         return callback(command);
  231 }
  232 
  233 /* adds a command back to the free command queue */
  234 void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
  235 {
  236         intrmask_t mask;
  237         mask = splbio();
  238         SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
  239         (sc->used_commands)--;
  240         splx(mask);
  241         if(!(sc->state & IPS_TIMEOUT))
  242                 ips_run_waiting_command(sc);
  243 }
  244 
  245 static int ips_diskdev_init(ips_softc_t *sc)
  246 {
  247         int i;
  248         for(i=0; i < IPS_MAX_NUM_DRIVES; i++){
  249                 if(sc->drives[i].state & IPS_LD_OKAY){
  250                         sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
  251                         device_set_ivars(sc->diskdev[i],(void *) i);
  252                 }
  253         }
  254         if(bus_generic_attach(sc->dev)){
  255                 device_printf(sc->dev, "Attaching bus failed\n");
  256         }
  257         return 0;
  258 }
  259 
  260 static int ips_diskdev_free(ips_softc_t *sc)
  261 {
  262         int i;
  263         int error = 0;
  264         for(i = 0; i < IPS_MAX_NUM_DRIVES; i++){
  265                 if(sc->diskdev[i])
  266                         error = device_delete_child(sc->dev, sc->diskdev[i]);
  267                         if(error)
  268                                 return error;
  269         }
  270         bus_generic_detach(sc->dev);
  271         return 0;
  272 }
  273 
  274 /* ips_timeout is periodically called to make sure no commands sent
  275  * to the card have become stuck.  If it finds a stuck command, it
  276  * sets a flag so the driver won't start any more commands and then
  277  * is periodically called to see if all outstanding commands have
  278  * either finished or timed out.  Once timed out, an attempt to
  279  * reinitialize the card is made.  If that fails, the driver gives
  280  * up and declares the card dead. */
  281 static void ips_timeout(void *arg)
  282 {
  283         intrmask_t mask;
  284         ips_softc_t *sc = arg;
  285         int i, state = 0;
  286         ips_command_t *command;
  287         command = &sc->commandarray[0];
  288         mask = splbio();
  289         for(i = 0; i < sc->max_cmds; i++){
  290                 if(!command[i].timeout){
  291                         continue;
  292                 }
  293                 command[i].timeout--;
  294                 if(!command[i].timeout){
  295                         if(!(sc->state & IPS_TIMEOUT)){
  296                                 sc->state |= IPS_TIMEOUT;
  297                                 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
  298                         }
  299                         command[i].status.value = IPS_ERROR_STATUS;
  300                         command[i].callback(&command[i]);
  301                         /* hmm, this should be enough cleanup */
  302                 } else
  303                         state = 1;
  304         }
  305         if(!state && (sc->state & IPS_TIMEOUT)){
  306                 if(sc->ips_adapter_reinit(sc, 1)){
  307                         device_printf(sc->dev, "AIEE! adapter reset failed, giving up and going home! Have a nice day.\n");
  308                         sc->state |= IPS_OFFLINE;
  309                         sc->state &= ~IPS_TIMEOUT;
  310                         /* Grr, I hate this solution. I run waiting commands
  311                            one at a time and error them out just before they 
  312                            would go to the card. This sucks. */
  313                 } else
  314                         sc->state &= ~IPS_TIMEOUT;
  315                 ips_run_waiting_command(sc);
  316         }
  317         if (sc->state != IPS_OFFLINE)
  318                 sc->timer = timeout(ips_timeout, sc, 10*hz);
  319         splx(mask);
  320 }
  321 
  322 /* check card and initialize it */
  323 int ips_adapter_init(ips_softc_t *sc)
  324 {
  325         DEVICE_PRINTF(1,sc->dev, "initializing\n");
  326         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  327                                 /* alignemnt */ 1,
  328                                 /* boundary  */ 0,
  329                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  330                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  331                                 /* filter    */ NULL,
  332                                 /* filterarg */ NULL,
  333                                 /* maxsize   */ IPS_COMMAND_LEN + 
  334                                                     IPS_MAX_SG_LEN,
  335                                 /* numsegs   */ 1,
  336                                 /* maxsegsize*/ IPS_COMMAND_LEN + 
  337                                                     IPS_MAX_SG_LEN,
  338                                 /* flags     */ 0,
  339                                 &sc->command_dmatag) != 0) {
  340                 device_printf(sc->dev, "can't alloc command dma tag\n");
  341                 goto error;
  342         }
  343         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  344                                 /* alignemnt */ 1,
  345                                 /* boundary  */ 0,
  346                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  347                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  348                                 /* filter    */ NULL,
  349                                 /* filterarg */ NULL,
  350                                 /* maxsize   */ IPS_MAX_IOBUF_SIZE,
  351                                 /* numsegs   */ IPS_MAX_SG_ELEMENTS,
  352                                 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
  353                                 /* flags     */ 0,
  354                                 &sc->sg_dmatag) != 0) {
  355                 device_printf(sc->dev, "can't alloc SG dma tag\n");
  356                 goto error;
  357         }
  358         /* create one command buffer until we know how many commands this card
  359            can handle */
  360         sc->max_cmds = 1;
  361         ips_cmdqueue_init(sc);
  362 
  363         if(sc->ips_adapter_reinit(sc, 0))
  364                 goto error;
  365 
  366         mtx_init(&sc->cmd_mtx, "ips command mutex", NULL, MTX_DEF);
  367         if(ips_get_adapter_info(sc) || ips_get_drive_info(sc)){
  368                 device_printf(sc->dev, "failed to get configuration data from device\n");
  369                 goto error;
  370         }
  371         ips_update_nvram(sc); /* no error check as failure doesn't matter */
  372 
  373         ips_cmdqueue_free(sc);
  374         if(sc->adapter_info.max_concurrent_cmds)
  375                 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
  376         else
  377                 sc->max_cmds = 32;
  378         if(ips_cmdqueue_init(sc)){
  379                 device_printf(sc->dev, "failed to initialize command buffers\n");
  380                 goto error;
  381         }
  382         sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
  383                                         S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
  384         sc->device_file->si_drv1 = sc;
  385         ips_diskdev_init(sc);
  386         sc->timer = timeout(ips_timeout, sc, 10*hz);
  387         return 0;
  388 
  389 error:
  390         ips_adapter_free(sc);
  391         return ENXIO;
  392 }
  393 
  394 /* see if we should reinitialize the card and wait for it to timeout or complete initialization */
  395 int ips_morpheus_reinit(ips_softc_t *sc, int force)
  396 {
  397         u_int32_t tmp;
  398         int i;
  399 
  400         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  401         if(!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
  402             (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp){
  403                 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
  404                 return 0;
  405         }
  406         ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
  407         ips_read_4(sc, MORPHEUS_REG_OIMR);
  408 
  409         device_printf(sc->dev, "resetting adapter, this may take up to 5 minutes\n");
  410         ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
  411         DELAY(5000000);
  412         pci_read_config(sc->dev, 0, 4);
  413 
  414         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  415         for(i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++){
  416                 DELAY(1000000);
  417                 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
  418                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  419         }
  420         if(tmp & MORPHEUS_BIT_POST1)
  421                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
  422 
  423         if( i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK){
  424                 device_printf(sc->dev,"Adapter error during initialization.\n");
  425                 return 1;
  426         }
  427         for(i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++){
  428                 DELAY(1000000); 
  429                 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
  430                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  431         }
  432         if(tmp & MORPHEUS_BIT_POST2)
  433                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
  434 
  435         if(i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)){
  436                 device_printf(sc->dev, "adapter failed config check\n");
  437                 return 1;
  438         }
  439         ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
  440         if(force && ips_clear_adapter(sc)){
  441                 device_printf(sc->dev, "adapter clear failed\n");
  442                 return 1;
  443         }
  444         return 0;
  445 }
  446 
  447 /* clean up so we can unload the driver. */
  448 int ips_adapter_free(ips_softc_t *sc)
  449 {
  450         int error = 0;
  451         intrmask_t mask;
  452         if(sc->state & IPS_DEV_OPEN)
  453                 return EBUSY;
  454         if((error = ips_diskdev_free(sc)))
  455                 return error;
  456         if(ips_cmdqueue_free(sc)){
  457                 device_printf(sc->dev,
  458                      "trying to exit when command queue is not empty!\n");
  459                 return EBUSY;
  460         }
  461         DEVICE_PRINTF(1, sc->dev, "free\n");
  462         mask = splbio();
  463         untimeout(ips_timeout, sc, sc->timer);
  464         splx(mask);
  465         if (mtx_initialized(&sc->cmd_mtx))
  466                 mtx_destroy(&sc->cmd_mtx);
  467 
  468         if(sc->sg_dmatag)
  469                 bus_dma_tag_destroy(sc->sg_dmatag);
  470         if(sc->command_dmatag)
  471                 bus_dma_tag_destroy(sc->command_dmatag);
  472         if(sc->device_file)
  473                 destroy_dev(sc->device_file);
  474         return 0;
  475 }
  476 
  477 void ips_morpheus_intr(void *void_sc)
  478 {
  479         ips_softc_t *sc = (ips_softc_t *)void_sc;
  480         u_int32_t oisr, iisr;
  481         int cmdnumber;
  482         ips_cmd_status_t status;
  483 
  484         iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
  485         oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
  486         PRINTF(9,"interrupt registers in:%x out:%x\n",iisr, oisr);
  487         if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
  488                 DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
  489                 return; 
  490         }
  491         while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
  492                 cmdnumber = status.fields.command_id;
  493                 sc->commandarray[cmdnumber].status.value = status.value;
  494                 sc->commandarray[cmdnumber].timeout = 0;
  495                 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
  496                 
  497 
  498                 DEVICE_PRINTF(9,sc->dev, "got command %d\n", cmdnumber);
  499         }
  500         return;
  501 }
  502 
  503 void ips_issue_morpheus_cmd(ips_command_t *command)
  504 {
  505         intrmask_t mask = splbio();
  506         /* hmmm, is there a cleaner way to do this? */
  507         if(command->sc->state & IPS_OFFLINE){
  508                 splx(mask);
  509                 command->status.value = IPS_ERROR_STATUS;
  510                 command->callback(command);
  511                 return;
  512         }
  513         command->timeout = 10;
  514         ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
  515         splx(mask);
  516 }
  517 
  518 static void ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,int segnum, int error)
  519 {
  520         ips_copper_queue_t *queue = queueptr;
  521         if(error){
  522                 return;
  523         }
  524         queue->base_phys_addr = segments[0].ds_addr;
  525 }
  526 
  527 static int ips_copperhead_queue_init(ips_softc_t *sc)
  528 {
  529         int error;
  530         bus_dma_tag_t dmatag;
  531         bus_dmamap_t dmamap;
  532         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  533                                 /* alignemnt */ 1,
  534                                 /* boundary  */ 0,
  535                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  536                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  537                                 /* filter    */ NULL,
  538                                 /* filterarg */ NULL,
  539                                 /* maxsize   */ sizeof(ips_copper_queue_t),
  540                                 /* numsegs   */ 1,
  541                                 /* maxsegsize*/ sizeof(ips_copper_queue_t),
  542                                 /* flags     */ 0,
  543                                 &dmatag) != 0) {
  544                 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
  545                 error = ENOMEM;
  546                 goto exit;
  547         }
  548         if(bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue), 
  549                             BUS_DMA_NOWAIT, &dmamap)){
  550                 error = ENOMEM;
  551                 goto exit;
  552         }
  553         bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
  554         sc->copper_queue->dmatag = dmatag;
  555         sc->copper_queue->dmamap = dmamap;
  556         sc->copper_queue->nextstatus = 1;
  557         bus_dmamap_load(dmatag, dmamap, 
  558                         &(sc->copper_queue->status[0]), IPS_MAX_CMD_NUM * 4, 
  559                         ips_copperhead_queue_callback, sc->copper_queue, 
  560                         BUS_DMA_NOWAIT);
  561         if(sc->copper_queue->base_phys_addr == 0){
  562                 error = ENOMEM;
  563                 goto exit;
  564         }
  565         ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
  566         ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr + 
  567                     IPS_MAX_CMD_NUM * 4);
  568         ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
  569         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
  570 
  571         
  572         return 0;
  573 exit:
  574         bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
  575         bus_dma_tag_destroy(dmatag);
  576         return error;
  577 }
  578 
  579 /* see if we should reinitialize the card and wait for it to timeout or complete initialization FIXME */
  580 int ips_copperhead_reinit(ips_softc_t *sc, int force)
  581 {
  582         int i, j;
  583         u_int32_t postcode = 0, configstatus = 0;
  584         ips_write_1(sc, COPPER_REG_SCPR, 0x80);
  585         ips_write_1(sc, COPPER_REG_SCPR, 0);
  586         device_printf(sc->dev, "reinitializing adapter, this could take several minutes.\n");
  587         for(j = 0; j < 2; j++){
  588                 postcode <<= 8;
  589                 for(i = 0; i < 45; i++){
  590                         if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
  591                                 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
  592                                 ips_write_1(sc, COPPER_REG_HISR, 
  593                                             COPPER_GHI_BIT);
  594                                 break;
  595                         } else
  596                                 DELAY(1000000);
  597                 }
  598                 if(i == 45)
  599                         return 1;
  600         }
  601         for(j = 0; j < 2; j++){
  602                 configstatus <<= 8;
  603                 for(i = 0; i < 240; i++){
  604                         if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
  605                                 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
  606                                 ips_write_1(sc, COPPER_REG_HISR, 
  607                                             COPPER_GHI_BIT);
  608                                 break;
  609                         } else
  610                                 DELAY(1000000);
  611                 }
  612                 if(i == 240)
  613                         return 1;
  614         }
  615         for(i = 0; i < 240; i++){
  616                 if(!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT)){
  617                         break;
  618                 } else
  619                         DELAY(1000000);
  620         }
  621         if(i == 240)
  622                 return 1;
  623         ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
  624         ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
  625         ips_copperhead_queue_init(sc);
  626         ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
  627         i = ips_read_1(sc, COPPER_REG_SCPR);
  628         ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
  629         if(!configstatus){
  630                 device_printf(sc->dev, "adapter initialization failed\n");
  631                 return 1;
  632         }
  633         if(force && ips_clear_adapter(sc)){
  634                 device_printf(sc->dev, "adapter clear failed\n");
  635                 return 1;
  636         }
  637         return 0;
  638 }
  639 static u_int32_t ips_copperhead_cmd_status(ips_softc_t *sc)
  640 {
  641         intrmask_t mask;
  642         u_int32_t value;
  643         int statnum = sc->copper_queue->nextstatus++;
  644         if(sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
  645                 sc->copper_queue->nextstatus = 0;
  646         mask = splbio();
  647         value = sc->copper_queue->status[statnum];
  648         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr + 
  649                     4 * statnum);
  650         splx(mask);
  651         return value;
  652 }
  653 
  654 
  655 void ips_copperhead_intr(void *void_sc)
  656 {
  657         ips_softc_t *sc = (ips_softc_t *)void_sc;
  658         int cmdnumber;
  659         ips_cmd_status_t status;
  660 
  661         while(ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT){
  662                 status.value = ips_copperhead_cmd_status(sc);
  663                 cmdnumber = status.fields.command_id;
  664                 sc->commandarray[cmdnumber].status.value = status.value;
  665                 sc->commandarray[cmdnumber].timeout = 0;
  666                 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
  667                 PRINTF(9, "ips: got command %d\n", cmdnumber);
  668         }
  669         return;
  670 }
  671 
  672 void ips_issue_copperhead_cmd(ips_command_t *command)
  673 {
  674         int i;
  675         intrmask_t mask = splbio();
  676         /* hmmm, is there a cleaner way to do this? */
  677         if(command->sc->state & IPS_OFFLINE){
  678                 splx(mask);
  679                 command->status.value = IPS_ERROR_STATUS;
  680                 command->callback(command);
  681                 return;
  682         }
  683         command->timeout = 10;
  684         for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
  685             i++ ){
  686                 if( i == 20){
  687 printf("sem bit still set, can't send a command\n");
  688                         splx(mask);
  689                         return;
  690                 }
  691                 DELAY(500);/* need to do a delay here */
  692         }
  693         ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
  694         ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
  695         splx(mask);
  696 }
  697 

Cache object: da644ce2d3236be9c51f0f868538a78f


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