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_commands.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_commands.c 114902 2003-05-11 06:36:49Z scottl $
   29  */
   30 
   31 
   32 #include <dev/ips/ips.h>
   33 
   34 /*
   35  * This is an interrupt callback.  It is called from
   36  * interrupt context when the adapter has completed the
   37  * command.  This very generic callback simply stores
   38  * the command's return value in command->arg and wake's
   39  * up anyone waiting on the command. 
   40  */
   41 static void ips_wakeup_callback(ips_command_t *command)
   42 {
   43         ips_cmd_status_t *status;
   44         status = command->arg;
   45         status->value = command->status.value;
   46         bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap, 
   47                         BUS_DMASYNC_POSTWRITE);
   48         mtx_lock(&command->sc->cmd_mtx);
   49         wakeup(status);
   50         mtx_unlock(&command->sc->cmd_mtx);
   51 }
   52 /* Below are a series of functions for sending an IO request
   53  * to the adapter.  The flow order is: start, send, callback, finish.
   54  * The caller must have already assembled an iorequest struct to hold
   55  * the details of the IO request. */
   56 static void ips_io_request_finish(ips_command_t *command)
   57 {
   58 
   59         struct bio *iobuf = command->arg;
   60         if(ips_read_request(iobuf)) {
   61                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
   62                                 BUS_DMASYNC_POSTREAD);
   63         } else {
   64                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
   65                                 BUS_DMASYNC_POSTWRITE);
   66         }
   67         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
   68         bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
   69         if(COMMAND_ERROR(&command->status)){
   70                 iobuf->bio_flags |=BIO_ERROR;
   71                 iobuf->bio_error = EIO;
   72         }
   73         ips_insert_free_cmd(command->sc, command);
   74         ipsd_finish(iobuf);
   75 }
   76 
   77 static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
   78 {
   79         ips_softc_t *sc;
   80         ips_command_t *command = cmdptr;
   81         ips_sg_element_t *sg_list;
   82         ips_io_cmd *command_struct;
   83         struct bio *iobuf = command->arg;
   84         int i, length = 0;
   85         u_int8_t cmdtype;
   86 
   87         sc = command->sc;
   88         if(error){
   89                 printf("ips: error = %d in ips_sg_request_callback\n", error);
   90                 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
   91                 bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
   92                 iobuf->bio_flags |= BIO_ERROR;
   93                 iobuf->bio_error = ENOMEM;
   94                 ips_insert_free_cmd(sc, command);
   95                 ipsd_finish(iobuf);
   96                 return;
   97         }
   98         command_struct = (ips_io_cmd *)command->command_buffer;
   99         command_struct->id = command->id;
  100         command_struct->drivenum = (uint32_t)iobuf->bio_driver1;
  101         if(segnum != 1){
  102                 if(ips_read_request(iobuf))
  103                         cmdtype = IPS_SG_READ_CMD;
  104                 else
  105                         cmdtype = IPS_SG_WRITE_CMD;
  106                 command_struct->segnum = segnum;
  107                 sg_list = (ips_sg_element_t *)((u_int8_t *)
  108                            command->command_buffer + IPS_COMMAND_LEN);
  109                 for(i = 0; i < segnum; i++){
  110                         sg_list[i].addr = segments[i].ds_addr;
  111                         sg_list[i].len = segments[i].ds_len;
  112                         length += segments[i].ds_len;
  113                 }
  114                 command_struct->buffaddr = 
  115                     (u_int32_t)command->command_phys_addr + IPS_COMMAND_LEN;
  116         } else {
  117                 if(ips_read_request(iobuf))
  118                         cmdtype = IPS_READ_CMD;
  119                 else
  120                         cmdtype = IPS_WRITE_CMD;
  121                 command_struct->buffaddr = segments[0].ds_addr;
  122                 length = segments[0].ds_len;
  123         }
  124         command_struct->command = cmdtype;
  125         command_struct->lba = iobuf->bio_pblkno;
  126         length = (length + IPS_BLKSIZE - 1)/IPS_BLKSIZE;
  127         command_struct->length = length;
  128         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  129                         BUS_DMASYNC_PREWRITE);
  130         if(ips_read_request(iobuf)) {
  131                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  132                                 BUS_DMASYNC_PREREAD);
  133         } else {
  134                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  135                                 BUS_DMASYNC_PREWRITE);
  136         }
  137         PRINTF(10, "ips test: command id: %d segments: %d blkno: %lld "
  138                 "pblkno: %lld length: %d, ds_len: %d\n", command->id, segnum,
  139                 iobuf->bio_blkno, iobuf->bio_pblkno,
  140                 length, segments[0].ds_len);
  141 
  142         sc->ips_issue_cmd(command);
  143         return;
  144 }
  145 
  146 static int ips_send_io_request(ips_command_t *command)
  147 {
  148         ips_softc_t *sc = command->sc;
  149         struct bio *iobuf = command->arg;
  150         command->data_dmatag = sc->sg_dmatag;
  151         if(bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)){
  152                 device_printf(sc->dev, "dmamap failed\n");
  153                 iobuf->bio_flags |= BIO_ERROR;
  154                 iobuf->bio_error = ENOMEM;
  155                 ips_insert_free_cmd(sc, command);
  156                 ipsd_finish(iobuf);
  157                 return 0;
  158         }
  159         command->callback = ips_io_request_finish;
  160         PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount);
  161         bus_dmamap_load(command->data_dmatag, command->data_dmamap,
  162                         iobuf->bio_data, iobuf->bio_bcount,
  163                         ips_io_request_callback, command, 0);
  164         return 0;
  165 } 
  166 
  167 void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf)
  168 {
  169         if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, 0)){
  170                 device_printf(sc->dev, "no mem for command slots!\n");
  171                 iobuf->bio_flags |= BIO_ERROR;
  172                 iobuf->bio_error = ENOMEM;
  173                 ipsd_finish(iobuf);
  174                 return;
  175         }
  176         return;
  177 }
  178 
  179 /* Below are a series of functions for sending an adapter info request 
  180  * to the adapter.  The flow order is: get, send, callback. It uses
  181  * the generic finish callback at the top of this file. 
  182  * This can be used to get configuration/status info from the card */
  183 static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  184 {
  185         ips_softc_t *sc;
  186         ips_command_t *command = cmdptr;
  187         ips_adapter_info_cmd *command_struct;
  188         sc = command->sc;
  189         if(error){
  190                 ips_cmd_status_t * status = command->arg;
  191                 status->value = IPS_ERROR_STATUS; /* a lovely error value */
  192                 ips_insert_free_cmd(sc, command);
  193                 printf("ips: error = %d in ips_get_adapter_info\n", error);
  194                 return;
  195         }
  196         command_struct = (ips_adapter_info_cmd *)command->command_buffer;
  197         command_struct->command = IPS_ADAPTER_INFO_CMD;
  198         command_struct->id = command->id;
  199         command_struct->buffaddr = segments[0].ds_addr;
  200 
  201         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  202                         BUS_DMASYNC_PREWRITE);
  203         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  204                         BUS_DMASYNC_PREREAD);
  205         sc->ips_issue_cmd(command);
  206 }
  207 
  208 
  209 
  210 static int ips_send_adapter_info_cmd(ips_command_t *command)
  211 {
  212         int error = 0;
  213         ips_softc_t *sc = command->sc;
  214         ips_cmd_status_t *status = command->arg;
  215 
  216         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  217                                 /* alignemnt */ 1,
  218                                 /* boundary  */ 0,
  219                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  220                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  221                                 /* filter    */ NULL,
  222                                 /* filterarg */ NULL,
  223                                 /* maxsize   */ IPS_ADAPTER_INFO_LEN,
  224                                 /* numsegs   */ 1,
  225                                 /* maxsegsize*/ IPS_ADAPTER_INFO_LEN,
  226                                 /* flags     */ 0,
  227                                 &command->data_dmatag) != 0) {
  228                 printf("ips: can't alloc dma tag for adapter status\n");
  229                 error = ENOMEM;
  230                 goto exit;
  231         }
  232         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  233            BUS_DMA_NOWAIT, &command->data_dmamap)){
  234                 error = ENOMEM;
  235                 goto exit;
  236         }
  237         command->callback = ips_wakeup_callback;
  238         mtx_lock(&sc->cmd_mtx);
  239         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  240                         command->data_buffer,IPS_ADAPTER_INFO_LEN, 
  241                         ips_adapter_info_callback, command, BUS_DMA_NOWAIT);
  242 
  243         if ((status->value == IPS_ERROR_STATUS) ||
  244             (msleep(status, &sc->cmd_mtx, 0, "ips", 30*hz) == EWOULDBLOCK))
  245                 error = ETIMEDOUT;
  246         mtx_unlock(&sc->cmd_mtx);
  247 
  248         if (error == 0) {
  249                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  250                                 BUS_DMASYNC_POSTREAD);
  251                 memcpy(&(sc->adapter_info), command->data_buffer, 
  252                         IPS_ADAPTER_INFO_LEN);
  253         }
  254         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  255 
  256 exit:
  257         /* I suppose I should clean up my memory allocations */
  258         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  259                         command->data_dmamap);
  260         bus_dma_tag_destroy(command->data_dmatag);
  261         ips_insert_free_cmd(sc, command);
  262         return error;
  263 }
  264 
  265 int ips_get_adapter_info(ips_softc_t *sc)
  266 {
  267         int error = 0;
  268         ips_cmd_status_t *status;
  269         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
  270         if(!status)
  271                 return ENOMEM;
  272         if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status, 
  273                             IPS_NOWAIT_FLAG) > 0){
  274                 device_printf(sc->dev, "unable to get adapter configuration\n");
  275                 free(status, M_DEVBUF);
  276                 return ENXIO;
  277         }
  278         if(COMMAND_ERROR(status)){
  279                 error = ENXIO;
  280         }
  281         free(status, M_DEVBUF);
  282         return error;
  283 }
  284 
  285 /* Below are a series of functions for sending a drive info request 
  286  * to the adapter.  The flow order is: get, send, callback. It uses
  287  * the generic finish callback at the top of this file. 
  288  * This can be used to get drive status info from the card */
  289 static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  290 {
  291         ips_softc_t *sc;
  292         ips_command_t *command = cmdptr;
  293         ips_drive_cmd *command_struct;
  294         sc = command->sc;
  295         if(error){
  296                 ips_cmd_status_t * status = command->arg;
  297                 status->value = IPS_ERROR_STATUS;
  298                 ips_insert_free_cmd(sc, command);
  299                 printf("ips: error = %d in ips_get_drive_info\n", error);
  300                 return;
  301         }
  302         command_struct = (ips_drive_cmd *)command->command_buffer;
  303         command_struct->command = IPS_DRIVE_INFO_CMD;
  304         command_struct->id = command->id;
  305         command_struct->buffaddr = segments[0].ds_addr;
  306 
  307         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  308                         BUS_DMASYNC_PREWRITE);
  309         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  310                         BUS_DMASYNC_PREREAD);
  311         sc->ips_issue_cmd(command);
  312 }
  313 
  314 static int ips_send_drive_info_cmd(ips_command_t *command)
  315 {
  316         int error = 0;
  317         ips_softc_t *sc = command->sc;
  318         ips_cmd_status_t *status = command->arg;
  319         ips_drive_info_t *driveinfo;
  320 
  321         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  322                                 /* alignemnt */ 1,
  323                                 /* boundary  */ 0,
  324                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  325                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  326                                 /* filter    */ NULL,
  327                                 /* filterarg */ NULL,
  328                                 /* maxsize   */ IPS_DRIVE_INFO_LEN,
  329                                 /* numsegs   */ 1,
  330                                 /* maxsegsize*/ IPS_DRIVE_INFO_LEN,
  331                                 /* flags     */ 0,
  332                                 &command->data_dmatag) != 0) {
  333                 printf("ips: can't alloc dma tag for drive status\n");
  334                 error = ENOMEM;
  335                 goto exit;
  336         }
  337         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  338                             BUS_DMA_NOWAIT, &command->data_dmamap)){
  339                 error = ENOMEM;
  340                 goto exit;
  341         }
  342         command->callback = ips_wakeup_callback;
  343         mtx_lock(&sc->cmd_mtx);
  344         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  345                         command->data_buffer,IPS_DRIVE_INFO_LEN, 
  346                         ips_drive_info_callback, command, BUS_DMA_NOWAIT);
  347         if ((status->value == IPS_ERROR_STATUS) ||
  348             (msleep(status, &sc->cmd_mtx, 0, "ips", 10*hz) == EWOULDBLOCK))
  349                 error = ETIMEDOUT;
  350         mtx_unlock(&sc->cmd_mtx);
  351 
  352         if (error == 0) {
  353                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  354                                 BUS_DMASYNC_POSTREAD);
  355                 driveinfo = command->data_buffer;
  356                 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8); 
  357                 sc->drivecount = driveinfo->drivecount;
  358                 device_printf(sc->dev, "logical drives: %d\n",sc->drivecount);
  359         }
  360         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  361 
  362 exit:
  363         /* I suppose I should clean up my memory allocations */
  364         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  365                         command->data_dmamap);
  366         bus_dma_tag_destroy(command->data_dmatag);
  367         ips_insert_free_cmd(sc, command);
  368         return error;
  369 
  370 }
  371 int ips_get_drive_info(ips_softc_t *sc)
  372 {
  373         int error = 0;
  374         ips_cmd_status_t *status;
  375         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
  376         if(!status)
  377                 return ENOMEM;
  378         if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status, 
  379                             IPS_NOWAIT_FLAG) > 0){
  380                 free(status, M_DEVBUF);
  381                 device_printf(sc->dev, "unable to get drive configuration\n");
  382                 return ENXIO;
  383         }
  384         if(COMMAND_ERROR(status)){
  385                 error = ENXIO;
  386         }
  387         free(status, M_DEVBUF);
  388         return error;
  389 }
  390 
  391 /* Below is a pair of functions for making sure data is safely
  392  * on disk by flushing the adapter's cache. */
  393 static int ips_send_flush_cache_cmd(ips_command_t *command)
  394 {
  395         ips_softc_t *sc = command->sc;
  396         ips_cmd_status_t *status = command->arg;
  397         ips_generic_cmd *command_struct;
  398 
  399         PRINTF(10,"ips test: got a command, building flush command\n");
  400         command->callback = ips_wakeup_callback;
  401         command_struct = (ips_generic_cmd *)command->command_buffer;
  402         command_struct->command = IPS_CACHE_FLUSH_CMD;
  403         command_struct->id = command->id;
  404         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  405                         BUS_DMASYNC_PREWRITE);
  406         mtx_lock(&sc->cmd_mtx);
  407         sc->ips_issue_cmd(command);
  408         if (status->value != IPS_ERROR_STATUS)
  409                 msleep(status, &sc->cmd_mtx, 0, "flush2", 0);
  410         mtx_unlock(&sc->cmd_mtx);
  411         ips_insert_free_cmd(sc, command);
  412         return 0;
  413 }
  414 
  415 int ips_flush_cache(ips_softc_t *sc)
  416 {
  417         ips_cmd_status_t *status;
  418         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
  419         if(!status)
  420                 return ENOMEM;
  421         device_printf(sc->dev, "flushing cache\n");
  422         if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status, 
  423                             IPS_NOWAIT_FLAG)){
  424                 free(status, M_DEVBUF);
  425                 device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n");
  426         }
  427         if(COMMAND_ERROR(status)){
  428                 device_printf(sc->dev, "ERROR: cache flush command failed!\n");
  429         }
  430         free(status, M_DEVBUF);
  431         return 0;
  432 }
  433 
  434 static void ips_write_nvram(ips_command_t *command){
  435         ips_softc_t *sc = command->sc;
  436         ips_rw_nvram_cmd *command_struct;
  437         ips_nvram_page5 *nvram;
  438 
  439         /*FIXME check for error */
  440         command->callback = ips_wakeup_callback;
  441         command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
  442         command_struct->command = IPS_RW_NVRAM_CMD;
  443         command_struct->id = command->id;
  444         command_struct->pagenum = 5;
  445         command_struct->rw      = 1; /*write*/
  446         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  447                                 BUS_DMASYNC_POSTREAD);
  448         nvram = command->data_buffer;
  449         strncpy(nvram->driver_high, IPS_VERSION_MAJOR, 4);
  450         strncpy(nvram->driver_low, IPS_VERSION_MINOR, 4);
  451         nvram->operating_system = IPS_OS_FREEBSD;       
  452         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  453                         BUS_DMASYNC_PREWRITE);
  454         sc->ips_issue_cmd(command);
  455 }
  456 
  457 static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  458 {
  459         ips_softc_t *sc;
  460         ips_command_t *command = cmdptr;
  461         ips_rw_nvram_cmd *command_struct;
  462         sc = command->sc;
  463         if(error){
  464                 ips_cmd_status_t * status = command->arg;
  465                 status->value = IPS_ERROR_STATUS;
  466                 ips_insert_free_cmd(sc, command);
  467                 printf("ips: error = %d in ips_read_nvram_callback\n", error);
  468                 return;
  469         }
  470         command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
  471         command_struct->command = IPS_RW_NVRAM_CMD;
  472         command_struct->id = command->id;
  473         command_struct->pagenum = 5;
  474         command_struct->rw = 0;
  475         command_struct->buffaddr = segments[0].ds_addr;
  476 
  477         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  478                         BUS_DMASYNC_PREWRITE);
  479         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  480                         BUS_DMASYNC_PREREAD);
  481         sc->ips_issue_cmd(command);
  482 }
  483 
  484 static int ips_read_nvram(ips_command_t *command){
  485         int error = 0;
  486         ips_softc_t *sc = command->sc;
  487         ips_cmd_status_t *status = command->arg;
  488 
  489         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  490                                 /* alignemnt */ 1,
  491                                 /* boundary  */ 0,
  492                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  493                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  494                                 /* filter    */ NULL,
  495                                 /* filterarg */ NULL,
  496                                 /* maxsize   */ IPS_NVRAM_PAGE_SIZE,
  497                                 /* numsegs   */ 1,
  498                                 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE,
  499                                 /* flags     */ 0,
  500                                 &command->data_dmatag) != 0) {
  501                 printf("ips: can't alloc dma tag for nvram\n");
  502                 error = ENOMEM;
  503                 goto exit;
  504         }
  505         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  506                             BUS_DMA_NOWAIT, &command->data_dmamap)){
  507                 error = ENOMEM;
  508                 goto exit;
  509         }
  510         command->callback = ips_write_nvram;
  511         mtx_lock(&sc->cmd_mtx);
  512         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  513                         command->data_buffer,IPS_NVRAM_PAGE_SIZE, 
  514                         ips_read_nvram_callback, command, BUS_DMA_NOWAIT);
  515         if ((status->value == IPS_ERROR_STATUS) ||
  516             (msleep(status, &sc->cmd_mtx, 0, "ips", 0) == EWOULDBLOCK))
  517                 error = ETIMEDOUT;
  518         mtx_unlock(&sc->cmd_mtx);
  519 
  520         if (error == 0) {
  521                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  522                                 BUS_DMASYNC_POSTWRITE);
  523         }
  524         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  525 
  526 exit:
  527         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  528                         command->data_dmamap);
  529         bus_dma_tag_destroy(command->data_dmatag);
  530         ips_insert_free_cmd(sc, command);
  531         return error;
  532 }
  533 
  534 int ips_update_nvram(ips_softc_t *sc)
  535 {
  536         ips_cmd_status_t *status;
  537         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
  538         if(!status)
  539                 return ENOMEM;
  540         if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){
  541                 free(status, M_DEVBUF);
  542                 device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n");
  543                 return 1;
  544         }
  545         if(COMMAND_ERROR(status)){
  546                 device_printf(sc->dev, "ERROR: nvram update command failed!\n");
  547         }
  548         free(status, M_DEVBUF);
  549         return 0;
  550 
  551 
  552 }
  553 
  554 
  555 static int ips_send_config_sync_cmd(ips_command_t *command)
  556 {
  557         ips_softc_t *sc = command->sc;
  558         ips_cmd_status_t *status = command->arg;
  559         ips_generic_cmd *command_struct;
  560 
  561         PRINTF(10,"ips test: got a command, building flush command\n");
  562         command->callback = ips_wakeup_callback;
  563         command_struct = (ips_generic_cmd *)command->command_buffer;
  564         command_struct->command = IPS_CONFIG_SYNC_CMD;
  565         command_struct->id = command->id;
  566         command_struct->reserve2 = IPS_POCL;
  567         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  568                         BUS_DMASYNC_PREWRITE);
  569         mtx_lock(&sc->cmd_mtx);
  570         sc->ips_issue_cmd(command);
  571         if (status->value != IPS_ERROR_STATUS)
  572                 msleep(status, &sc->cmd_mtx, 0, "ipssyn", 0);
  573         mtx_unlock(&sc->cmd_mtx);
  574         ips_insert_free_cmd(sc, command);
  575         return 0;
  576 }
  577 
  578 static int ips_send_error_table_cmd(ips_command_t *command)
  579 {
  580         ips_softc_t *sc = command->sc;
  581         ips_cmd_status_t *status = command->arg;
  582         ips_generic_cmd *command_struct;
  583 
  584         PRINTF(10,"ips test: got a command, building errortable command\n");
  585         command->callback = ips_wakeup_callback;
  586         command_struct = (ips_generic_cmd *)command->command_buffer;
  587         command_struct->command = IPS_ERROR_TABLE_CMD;
  588         command_struct->id = command->id;
  589         command_struct->reserve2 = IPS_CSL;
  590         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  591                         BUS_DMASYNC_PREWRITE);
  592         mtx_lock(&sc->cmd_mtx);
  593         sc->ips_issue_cmd(command);
  594         if (status->value != IPS_ERROR_STATUS)
  595                 msleep(status, &sc->cmd_mtx, 0, "ipsetc", 0);
  596         mtx_unlock(&sc->cmd_mtx);
  597         ips_insert_free_cmd(sc, command);
  598         return 0;
  599 }
  600 
  601 
  602 int ips_clear_adapter(ips_softc_t *sc)
  603 {
  604         ips_cmd_status_t *status;
  605         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
  606         if(!status)
  607                 return ENOMEM;
  608         device_printf(sc->dev, "syncing config\n");
  609         if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status, 
  610                             IPS_NOWAIT_FLAG)){
  611                 free(status, M_DEVBUF);
  612                 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
  613                 return 1;
  614         }
  615         if(COMMAND_ERROR(status)){
  616                 free(status, M_DEVBUF);
  617                 device_printf(sc->dev, "ERROR: cache sync command failed!\n");
  618                 return 1;
  619         }
  620 
  621         device_printf(sc->dev, "clearing error table\n");
  622         if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status, 
  623                             IPS_NOWAIT_FLAG)){
  624                 free(status, M_DEVBUF);
  625                 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
  626                 return 1;
  627         }
  628         if(COMMAND_ERROR(status)){
  629                 device_printf(sc->dev, "ERROR: etable command failed!\n");
  630                 free(status, M_DEVBUF);
  631                 return 1;
  632         }
  633 
  634         free(status, M_DEVBUF);
  635         return 0;
  636 }

Cache object: a031609f999a923d900cc5fc0680e2e7


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