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

Cache object: 15475e5b69522d4cd601c8ba0d411161


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