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  * Written by: David Jeffery
    3  * Copyright (c) 2002 Adaptec Inc.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   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  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/5.2/sys/dev/ips/ips_commands.c 124170 2004-01-06 15:52:23Z mbr $");
   30 
   31 #include <dev/ips/ips.h>
   32 
   33 /*
   34  * This is an interrupt callback.  It is called from
   35  * interrupt context when the adapter has completed the
   36  * command.  This very generic callback simply stores
   37  * the command's return value in command->arg and wake's
   38  * up anyone waiting on the command. 
   39  */
   40 static void ips_wakeup_callback(ips_command_t *command)
   41 {
   42         ips_cmd_status_t *status;
   43         status = command->arg;
   44         status->value = command->status.value;
   45         bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap, 
   46                         BUS_DMASYNC_POSTWRITE);
   47         mtx_lock(&command->sc->cmd_mtx);
   48         wakeup(status);
   49         mtx_unlock(&command->sc->cmd_mtx);
   50 }
   51 /* Below are a series of functions for sending an IO request
   52  * to the adapter.  The flow order is: start, send, callback, finish.
   53  * The caller must have already assembled an iorequest struct to hold
   54  * the details of the IO request. */
   55 static void ips_io_request_finish(ips_command_t *command)
   56 {
   57 
   58         struct bio *iobuf = command->arg;
   59         if(ips_read_request(iobuf)) {
   60                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
   61                                 BUS_DMASYNC_POSTREAD);
   62         } else {
   63                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
   64                                 BUS_DMASYNC_POSTWRITE);
   65         }
   66         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
   67         bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
   68         if(COMMAND_ERROR(&command->status)){
   69                 iobuf->bio_flags |=BIO_ERROR;
   70                 iobuf->bio_error = EIO;
   71         }
   72         ips_insert_free_cmd(command->sc, command);
   73         ipsd_finish(iobuf);
   74 }
   75 
   76 static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
   77 {
   78         ips_softc_t *sc;
   79         ips_command_t *command = cmdptr;
   80         ips_sg_element_t *sg_list;
   81         ips_io_cmd *command_struct;
   82         struct bio *iobuf = command->arg;
   83         int i, length = 0;
   84         u_int8_t cmdtype;
   85 
   86         sc = command->sc;
   87         if(error){
   88                 printf("ips: error = %d in ips_sg_request_callback\n", error);
   89                 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
   90                 bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
   91                 iobuf->bio_flags |= BIO_ERROR;
   92                 iobuf->bio_error = ENOMEM;
   93                 ips_insert_free_cmd(sc, command);
   94                 ipsd_finish(iobuf);
   95                 return;
   96         }
   97         command_struct = (ips_io_cmd *)command->command_buffer;
   98         command_struct->id = command->id;
   99         command_struct->drivenum = (uintptr_t)iobuf->bio_driver1;
  100         if(segnum != 1){
  101                 if(ips_read_request(iobuf))
  102                         cmdtype = IPS_SG_READ_CMD;
  103                 else
  104                         cmdtype = IPS_SG_WRITE_CMD;
  105                 command_struct->segnum = segnum;
  106                 sg_list = (ips_sg_element_t *)((u_int8_t *)
  107                            command->command_buffer + IPS_COMMAND_LEN);
  108                 for(i = 0; i < segnum; i++){
  109                         sg_list[i].addr = segments[i].ds_addr;
  110                         sg_list[i].len = segments[i].ds_len;
  111                         length += segments[i].ds_len;
  112                 }
  113                 command_struct->buffaddr = 
  114                     (u_int32_t)command->command_phys_addr + IPS_COMMAND_LEN;
  115         } else {
  116                 if(ips_read_request(iobuf))
  117                         cmdtype = IPS_READ_CMD;
  118                 else
  119                         cmdtype = IPS_WRITE_CMD;
  120                 command_struct->buffaddr = segments[0].ds_addr;
  121                 length = segments[0].ds_len;
  122         }
  123         command_struct->command = cmdtype;
  124         command_struct->lba = iobuf->bio_pblkno;
  125         length = (length + IPS_BLKSIZE - 1)/IPS_BLKSIZE;
  126         command_struct->length = length;
  127         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  128                         BUS_DMASYNC_PREWRITE);
  129         if(ips_read_request(iobuf)) {
  130                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  131                                 BUS_DMASYNC_PREREAD);
  132         } else {
  133                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  134                                 BUS_DMASYNC_PREWRITE);
  135         }
  136         PRINTF(10, "ips test: command id: %d segments: %d "
  137                 "pblkno: %lld length: %d, ds_len: %d\n", command->id, segnum,
  138                 iobuf->bio_pblkno,
  139                 length, segments[0].ds_len);
  140 
  141         sc->ips_issue_cmd(command);
  142         return;
  143 }
  144 
  145 static int ips_send_io_request(ips_command_t *command)
  146 {
  147         ips_softc_t *sc = command->sc;
  148         struct bio *iobuf = command->arg;
  149         command->data_dmatag = sc->sg_dmatag;
  150         if(bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)){
  151                 device_printf(sc->dev, "dmamap failed\n");
  152                 iobuf->bio_flags |= BIO_ERROR;
  153                 iobuf->bio_error = ENOMEM;
  154                 ips_insert_free_cmd(sc, command);
  155                 ipsd_finish(iobuf);
  156                 return 0;
  157         }
  158         command->callback = ips_io_request_finish;
  159         PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount);
  160         bus_dmamap_load(command->data_dmatag, command->data_dmamap,
  161                         iobuf->bio_data, iobuf->bio_bcount,
  162                         ips_io_request_callback, command, 0);
  163         return 0;
  164 } 
  165 
  166 void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf)
  167 {
  168         if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, 0)){
  169                 device_printf(sc->dev, "no mem for command slots!\n");
  170                 iobuf->bio_flags |= BIO_ERROR;
  171                 iobuf->bio_error = ENOMEM;
  172                 ipsd_finish(iobuf);
  173                 return;
  174         }
  175         return;
  176 }
  177 
  178 /* Below are a series of functions for sending an adapter info request 
  179  * to the adapter.  The flow order is: get, send, callback. It uses
  180  * the generic finish callback at the top of this file. 
  181  * This can be used to get configuration/status info from the card */
  182 static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  183 {
  184         ips_softc_t *sc;
  185         ips_command_t *command = cmdptr;
  186         ips_adapter_info_cmd *command_struct;
  187         sc = command->sc;
  188         if(error){
  189                 ips_cmd_status_t * status = command->arg;
  190                 status->value = IPS_ERROR_STATUS; /* a lovely error value */
  191                 ips_insert_free_cmd(sc, command);
  192                 printf("ips: error = %d in ips_get_adapter_info\n", error);
  193                 return;
  194         }
  195         command_struct = (ips_adapter_info_cmd *)command->command_buffer;
  196         command_struct->command = IPS_ADAPTER_INFO_CMD;
  197         command_struct->id = command->id;
  198         command_struct->buffaddr = segments[0].ds_addr;
  199 
  200         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  201                         BUS_DMASYNC_PREWRITE);
  202         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  203                         BUS_DMASYNC_PREREAD);
  204         sc->ips_issue_cmd(command);
  205 }
  206 
  207 
  208 
  209 static int ips_send_adapter_info_cmd(ips_command_t *command)
  210 {
  211         int error = 0;
  212         ips_softc_t *sc = command->sc;
  213         ips_cmd_status_t *status = command->arg;
  214 
  215         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  216                                 /* alignemnt */ 1,
  217                                 /* boundary  */ 0,
  218                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  219                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  220                                 /* filter    */ NULL,
  221                                 /* filterarg */ NULL,
  222                                 /* maxsize   */ IPS_ADAPTER_INFO_LEN,
  223                                 /* numsegs   */ 1,
  224                                 /* maxsegsize*/ IPS_ADAPTER_INFO_LEN,
  225                                 /* flags     */ 0,
  226                                 /* lockfunc  */ busdma_lock_mutex,
  227                                 /* lockarg   */ &Giant,
  228                                 &command->data_dmatag) != 0) {
  229                 printf("ips: can't alloc dma tag for adapter status\n");
  230                 error = ENOMEM;
  231                 goto exit;
  232         }
  233         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  234            BUS_DMA_NOWAIT, &command->data_dmamap)){
  235                 error = ENOMEM;
  236                 goto exit;
  237         }
  238         command->callback = ips_wakeup_callback;
  239         mtx_lock(&sc->cmd_mtx);
  240         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  241                         command->data_buffer,IPS_ADAPTER_INFO_LEN, 
  242                         ips_adapter_info_callback, command, BUS_DMA_NOWAIT);
  243 
  244         if ((status->value == IPS_ERROR_STATUS) ||
  245             (msleep(status, &sc->cmd_mtx, 0, "ips", 30*hz) == EWOULDBLOCK))
  246                 error = ETIMEDOUT;
  247         mtx_unlock(&sc->cmd_mtx);
  248 
  249         if (error == 0) {
  250                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  251                                 BUS_DMASYNC_POSTREAD);
  252                 memcpy(&(sc->adapter_info), command->data_buffer, 
  253                         IPS_ADAPTER_INFO_LEN);
  254         }
  255         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  256 
  257 exit:
  258         /* I suppose I should clean up my memory allocations */
  259         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  260                         command->data_dmamap);
  261         bus_dma_tag_destroy(command->data_dmatag);
  262         ips_insert_free_cmd(sc, command);
  263         return error;
  264 }
  265 
  266 int ips_get_adapter_info(ips_softc_t *sc)
  267 {
  268         int error = 0;
  269         ips_cmd_status_t *status;
  270         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  271         if(!status)
  272                 return ENOMEM;
  273         if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status, 
  274                             IPS_NOWAIT_FLAG) > 0){
  275                 device_printf(sc->dev, "unable to get adapter configuration\n");
  276                 free(status, M_DEVBUF);
  277                 return ENXIO;
  278         }
  279         if (COMMAND_ERROR(status)){
  280                 error = ENXIO;
  281         }
  282         free(status, M_DEVBUF);
  283         return error;
  284 }
  285 
  286 /* Below are a series of functions for sending a drive info request 
  287  * to the adapter.  The flow order is: get, send, callback. It uses
  288  * the generic finish callback at the top of this file. 
  289  * This can be used to get drive status info from the card */
  290 static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  291 {
  292         ips_softc_t *sc;
  293         ips_command_t *command = cmdptr;
  294         ips_drive_cmd *command_struct;
  295         sc = command->sc;
  296         if(error){
  297                 ips_cmd_status_t * status = command->arg;
  298                 status->value = IPS_ERROR_STATUS;
  299                 ips_insert_free_cmd(sc, command);
  300                 printf("ips: error = %d in ips_get_drive_info\n", error);
  301                 return;
  302         }
  303         command_struct = (ips_drive_cmd *)command->command_buffer;
  304         command_struct->command = IPS_DRIVE_INFO_CMD;
  305         command_struct->id = command->id;
  306         command_struct->buffaddr = segments[0].ds_addr;
  307 
  308         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  309                         BUS_DMASYNC_PREWRITE);
  310         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  311                         BUS_DMASYNC_PREREAD);
  312         sc->ips_issue_cmd(command);
  313 }
  314 
  315 static int ips_send_drive_info_cmd(ips_command_t *command)
  316 {
  317         int error = 0;
  318         ips_softc_t *sc = command->sc;
  319         ips_cmd_status_t *status = command->arg;
  320         ips_drive_info_t *driveinfo;
  321 
  322         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  323                                 /* alignemnt */ 1,
  324                                 /* boundary  */ 0,
  325                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  326                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  327                                 /* filter    */ NULL,
  328                                 /* filterarg */ NULL,
  329                                 /* maxsize   */ IPS_DRIVE_INFO_LEN,
  330                                 /* numsegs   */ 1,
  331                                 /* maxsegsize*/ IPS_DRIVE_INFO_LEN,
  332                                 /* flags     */ 0,
  333                                 /* lockfunc  */ busdma_lock_mutex,
  334                                 /* lockarg   */ &Giant,
  335                                 &command->data_dmatag) != 0) {
  336                 printf("ips: can't alloc dma tag for drive status\n");
  337                 error = ENOMEM;
  338                 goto exit;
  339         }
  340         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  341                             BUS_DMA_NOWAIT, &command->data_dmamap)){
  342                 error = ENOMEM;
  343                 goto exit;
  344         }
  345         command->callback = ips_wakeup_callback;
  346         mtx_lock(&sc->cmd_mtx);
  347         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  348                         command->data_buffer,IPS_DRIVE_INFO_LEN, 
  349                         ips_drive_info_callback, command, BUS_DMA_NOWAIT);
  350         if ((status->value == IPS_ERROR_STATUS) ||
  351             (msleep(status, &sc->cmd_mtx, 0, "ips", 10*hz) == EWOULDBLOCK))
  352                 error = ETIMEDOUT;
  353         mtx_unlock(&sc->cmd_mtx);
  354 
  355         if (error == 0) {
  356                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  357                                 BUS_DMASYNC_POSTREAD);
  358                 driveinfo = command->data_buffer;
  359                 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8); 
  360                 sc->drivecount = driveinfo->drivecount;
  361                 device_printf(sc->dev, "logical drives: %d\n",sc->drivecount);
  362         }
  363         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  364 
  365 exit:
  366         /* I suppose I should clean up my memory allocations */
  367         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  368                         command->data_dmamap);
  369         bus_dma_tag_destroy(command->data_dmatag);
  370         ips_insert_free_cmd(sc, command);
  371         return error;
  372 
  373 }
  374 int ips_get_drive_info(ips_softc_t *sc)
  375 {
  376         int error = 0;
  377         ips_cmd_status_t *status;
  378         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  379         if(!status)
  380                 return ENOMEM;
  381         if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status, 
  382                             IPS_NOWAIT_FLAG) > 0){
  383                 free(status, M_DEVBUF);
  384                 device_printf(sc->dev, "unable to get drive configuration\n");
  385                 return ENXIO;
  386         }
  387         if(COMMAND_ERROR(status)){
  388                 error = ENXIO;
  389         }
  390         free(status, M_DEVBUF);
  391         return error;
  392 }
  393 
  394 /* Below is a pair of functions for making sure data is safely
  395  * on disk by flushing the adapter's cache. */
  396 static int ips_send_flush_cache_cmd(ips_command_t *command)
  397 {
  398         ips_softc_t *sc = command->sc;
  399         ips_cmd_status_t *status = command->arg;
  400         ips_generic_cmd *command_struct;
  401 
  402         PRINTF(10,"ips test: got a command, building flush command\n");
  403         command->callback = ips_wakeup_callback;
  404         command_struct = (ips_generic_cmd *)command->command_buffer;
  405         command_struct->command = IPS_CACHE_FLUSH_CMD;
  406         command_struct->id = command->id;
  407         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  408                         BUS_DMASYNC_PREWRITE);
  409         mtx_lock(&sc->cmd_mtx);
  410         sc->ips_issue_cmd(command);
  411         if (status->value != IPS_ERROR_STATUS)
  412                 msleep(status, &sc->cmd_mtx, 0, "flush2", 0);
  413         mtx_unlock(&sc->cmd_mtx);
  414         ips_insert_free_cmd(sc, command);
  415         return 0;
  416 }
  417 
  418 int ips_flush_cache(ips_softc_t *sc)
  419 {
  420         ips_cmd_status_t *status;
  421         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  422         if(!status)
  423                 return ENOMEM;
  424         device_printf(sc->dev, "flushing cache\n");
  425         if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status, 
  426                             IPS_NOWAIT_FLAG)){
  427                 free(status, M_DEVBUF);
  428                 device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n");
  429         }
  430         if(COMMAND_ERROR(status)){
  431                 device_printf(sc->dev, "ERROR: cache flush command failed!\n");
  432         }
  433         free(status, M_DEVBUF);
  434         return 0;
  435 }
  436 
  437 /* Simplified localtime to provide timevalues for ffdc.
  438  * Taken from libc/stdtime/localtime.c
  439  */
  440 void static ips_ffdc_settime(ips_adapter_ffdc_cmd *command, time_t sctime)
  441 {
  442         long    days, rem, y;
  443         int     yleap, *ip, month;
  444         int     year_lengths[2] = { IPS_DAYSPERNYEAR, IPS_DAYSPERLYEAR };
  445         int     mon_lengths[2][IPS_MONSPERYEAR] = {
  446                 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  447                 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  448         };
  449 
  450         days = sctime / IPS_SECSPERDAY;
  451         rem  = sctime % IPS_SECSPERDAY;
  452 
  453         command->hour = rem / IPS_SECSPERHOUR;
  454         rem           = rem % IPS_SECSPERHOUR;
  455 
  456         command->minute = rem / IPS_SECSPERMIN;
  457         command->second = rem % IPS_SECSPERMIN;
  458 
  459         y = IPS_EPOCH_YEAR;
  460         while (days < 0 || days >= (long) year_lengths[yleap = ips_isleap(y)]) {
  461                 long    newy;
  462 
  463                 newy = y + days / IPS_DAYSPERNYEAR;
  464                 if (days < 0)
  465                         --newy;
  466                 days -= (newy - y) * IPS_DAYSPERNYEAR +
  467                         IPS_LEAPS_THRU_END_OF(newy - 1) -
  468                         IPS_LEAPS_THRU_END_OF(y - 1);
  469                 y = newy;
  470         }
  471         command->yearH = y / 100;
  472         command->yearL = y % 100;
  473         ip = mon_lengths[yleap];
  474         for(month = 0; days >= (long) ip[month]; ++month)
  475                 days = days - (long) ip[month];
  476         command->month = month + 1;
  477         command->day = days + 1;
  478 }
  479 
  480 static int ips_send_ffdc_reset_cmd(ips_command_t *command)
  481 {
  482         ips_softc_t *sc = command->sc;
  483         ips_cmd_status_t *status = command->arg;
  484         ips_adapter_ffdc_cmd *command_struct;
  485 
  486         PRINTF(10,"ips test: got a command, building ffdc reset command\n");
  487         command->callback = ips_wakeup_callback;
  488         command_struct = (ips_adapter_ffdc_cmd *)command->command_buffer;
  489         command_struct->command = IPS_FFDC_CMD;
  490         command_struct->id = command->id;
  491         command_struct->reset_count = sc->ffdc_resetcount;
  492         command_struct->reset_type  = 0x0;
  493         ips_ffdc_settime(command_struct, sc->ffdc_resettime.tv_sec);
  494 
  495         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
  496                         BUS_DMASYNC_PREWRITE);
  497         mtx_lock(&sc->cmd_mtx);
  498         sc->ips_issue_cmd(command);
  499         if (status->value != IPS_ERROR_STATUS)
  500                 msleep(status, &sc->cmd_mtx, 0, "ffdc", 0);
  501         mtx_unlock(&sc->cmd_mtx);
  502         ips_insert_free_cmd(sc, command);
  503         return 0;
  504 }
  505 
  506 int ips_ffdc_reset(ips_softc_t *sc)
  507 {
  508         ips_cmd_status_t *status;
  509         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  510         if(!status)
  511                 return ENOMEM;
  512         if(ips_get_free_cmd(sc, ips_send_ffdc_reset_cmd, status,
  513                             IPS_NOWAIT_FLAG)){
  514                 free(status, M_DEVBUF);
  515                 device_printf(sc->dev, "ERROR: unable to get a command! can't send ffdc reset!\n");
  516         }
  517         if(COMMAND_ERROR(status)){
  518                 device_printf(sc->dev, "ERROR: ffdc reset command failed!\n");
  519         }
  520         free(status, M_DEVBUF);
  521         return 0;
  522 }
  523 
  524 static void ips_write_nvram(ips_command_t *command){
  525         ips_softc_t *sc = command->sc;
  526         ips_rw_nvram_cmd *command_struct;
  527         ips_nvram_page5 *nvram;
  528 
  529         /*FIXME check for error */
  530         command->callback = ips_wakeup_callback;
  531         command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
  532         command_struct->command = IPS_RW_NVRAM_CMD;
  533         command_struct->id = command->id;
  534         command_struct->pagenum = 5;
  535         command_struct->rw      = 1; /*write*/
  536         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  537                                 BUS_DMASYNC_POSTREAD);
  538         nvram = command->data_buffer;
  539         /* retrieve adapter info and save in sc */
  540         sc->adapter_type = nvram->adapter_type;
  541 
  542         strncpy(nvram->driver_high, IPS_VERSION_MAJOR, 4);
  543         strncpy(nvram->driver_low, IPS_VERSION_MINOR, 4);
  544         nvram->operating_system = IPS_OS_FREEBSD;       
  545         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  546                         BUS_DMASYNC_PREWRITE);
  547         sc->ips_issue_cmd(command);
  548 }
  549 
  550 static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  551 {
  552         ips_softc_t *sc;
  553         ips_command_t *command = cmdptr;
  554         ips_rw_nvram_cmd *command_struct;
  555         sc = command->sc;
  556         if(error){
  557                 ips_cmd_status_t * status = command->arg;
  558                 status->value = IPS_ERROR_STATUS;
  559                 ips_insert_free_cmd(sc, command);
  560                 printf("ips: error = %d in ips_read_nvram_callback\n", error);
  561                 return;
  562         }
  563         command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
  564         command_struct->command = IPS_RW_NVRAM_CMD;
  565         command_struct->id = command->id;
  566         command_struct->pagenum = 5;
  567         command_struct->rw = 0;
  568         command_struct->buffaddr = segments[0].ds_addr;
  569 
  570         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  571                         BUS_DMASYNC_PREWRITE);
  572         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  573                         BUS_DMASYNC_PREREAD);
  574         sc->ips_issue_cmd(command);
  575 }
  576 
  577 static int ips_read_nvram(ips_command_t *command){
  578         int error = 0;
  579         ips_softc_t *sc = command->sc;
  580         ips_cmd_status_t *status = command->arg;
  581 
  582         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  583                                 /* alignemnt */ 1,
  584                                 /* boundary  */ 0,
  585                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  586                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  587                                 /* filter    */ NULL,
  588                                 /* filterarg */ NULL,
  589                                 /* maxsize   */ IPS_NVRAM_PAGE_SIZE,
  590                                 /* numsegs   */ 1,
  591                                 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE,
  592                                 /* flags     */ 0,
  593                                 /* lockfunc  */ busdma_lock_mutex,
  594                                 /* lockarg   */ &Giant,
  595                                 &command->data_dmatag) != 0) {
  596                 printf("ips: can't alloc dma tag for nvram\n");
  597                 error = ENOMEM;
  598                 goto exit;
  599         }
  600         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  601                             BUS_DMA_NOWAIT, &command->data_dmamap)){
  602                 error = ENOMEM;
  603                 goto exit;
  604         }
  605         command->callback = ips_write_nvram;
  606         mtx_lock(&sc->cmd_mtx);
  607         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  608                         command->data_buffer,IPS_NVRAM_PAGE_SIZE, 
  609                         ips_read_nvram_callback, command, BUS_DMA_NOWAIT);
  610         if ((status->value == IPS_ERROR_STATUS) ||
  611             (msleep(status, &sc->cmd_mtx, 0, "ips", 0) == EWOULDBLOCK))
  612                 error = ETIMEDOUT;
  613         mtx_unlock(&sc->cmd_mtx);
  614 
  615         if (error == 0) {
  616                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  617                                 BUS_DMASYNC_POSTWRITE);
  618         }
  619         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  620 
  621 exit:
  622         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  623                         command->data_dmamap);
  624         bus_dma_tag_destroy(command->data_dmatag);
  625         ips_insert_free_cmd(sc, command);
  626         return error;
  627 }
  628 
  629 int ips_update_nvram(ips_softc_t *sc)
  630 {
  631         ips_cmd_status_t *status;
  632         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  633         if(!status)
  634                 return ENOMEM;
  635         if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){
  636                 free(status, M_DEVBUF);
  637                 device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n");
  638                 return 1;
  639         }
  640         if(COMMAND_ERROR(status)){
  641                 device_printf(sc->dev, "ERROR: nvram update command failed!\n");
  642         }
  643         free(status, M_DEVBUF);
  644         return 0;
  645 
  646 
  647 }
  648 
  649 
  650 static int ips_send_config_sync_cmd(ips_command_t *command)
  651 {
  652         ips_softc_t *sc = command->sc;
  653         ips_cmd_status_t *status = command->arg;
  654         ips_generic_cmd *command_struct;
  655 
  656         PRINTF(10,"ips test: got a command, building flush command\n");
  657         command->callback = ips_wakeup_callback;
  658         command_struct = (ips_generic_cmd *)command->command_buffer;
  659         command_struct->command = IPS_CONFIG_SYNC_CMD;
  660         command_struct->id = command->id;
  661         command_struct->reserve2 = IPS_POCL;
  662         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  663                         BUS_DMASYNC_PREWRITE);
  664         mtx_lock(&sc->cmd_mtx);
  665         sc->ips_issue_cmd(command);
  666         if (status->value != IPS_ERROR_STATUS)
  667                 msleep(status, &sc->cmd_mtx, 0, "ipssyn", 0);
  668         mtx_unlock(&sc->cmd_mtx);
  669         ips_insert_free_cmd(sc, command);
  670         return 0;
  671 }
  672 
  673 static int ips_send_error_table_cmd(ips_command_t *command)
  674 {
  675         ips_softc_t *sc = command->sc;
  676         ips_cmd_status_t *status = command->arg;
  677         ips_generic_cmd *command_struct;
  678 
  679         PRINTF(10,"ips test: got a command, building errortable command\n");
  680         command->callback = ips_wakeup_callback;
  681         command_struct = (ips_generic_cmd *)command->command_buffer;
  682         command_struct->command = IPS_ERROR_TABLE_CMD;
  683         command_struct->id = command->id;
  684         command_struct->reserve2 = IPS_CSL;
  685         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  686                         BUS_DMASYNC_PREWRITE);
  687         mtx_lock(&sc->cmd_mtx);
  688         sc->ips_issue_cmd(command);
  689         if (status->value != IPS_ERROR_STATUS)
  690                 msleep(status, &sc->cmd_mtx, 0, "ipsetc", 0);
  691         mtx_unlock(&sc->cmd_mtx);
  692         ips_insert_free_cmd(sc, command);
  693         return 0;
  694 }
  695 
  696 
  697 int ips_clear_adapter(ips_softc_t *sc)
  698 {
  699         ips_cmd_status_t *status;
  700         status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  701         if(!status)
  702                 return ENOMEM;
  703         device_printf(sc->dev, "syncing config\n");
  704         if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status, 
  705                             IPS_NOWAIT_FLAG)){
  706                 free(status, M_DEVBUF);
  707                 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
  708                 return 1;
  709         }
  710         if(COMMAND_ERROR(status)){
  711                 free(status, M_DEVBUF);
  712                 device_printf(sc->dev, "ERROR: cache sync command failed!\n");
  713                 return 1;
  714         }
  715 
  716         device_printf(sc->dev, "clearing error table\n");
  717         if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status, 
  718                             IPS_NOWAIT_FLAG)){
  719                 free(status, M_DEVBUF);
  720                 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
  721                 return 1;
  722         }
  723         if(COMMAND_ERROR(status)){
  724                 device_printf(sc->dev, "ERROR: etable command failed!\n");
  725                 free(status, M_DEVBUF);
  726                 return 1;
  727         }
  728 
  729         free(status, M_DEVBUF);
  730         return 0;
  731 }

Cache object: 95c1157073eb618d475b0e43ccda9aba


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