2 * Written by: David Jeffery
3 * Copyright (c) 2002 Adaptec Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
27 * $FreeBSD: src/sys/dev/ips/ips_commands.c,v 1.10 2004/05/30 04:01:29 scottl Exp $
28 * $DragonFly: src/sys/dev/raid/ips/ips_commands.c,v 1.9 2005/08/09 16:23:13 dillon Exp $
31 #include <dev/raid/ips/ips.h>
34 ips_timed_wait(ips_command_t *command, const char *id, int timo)
38 while (command->completed == 0) {
40 if (command->completed == 0)
41 error = tsleep(&command->completed, 0, id, timo);
43 if (error == EWOULDBLOCK) {
52 * This is an interrupt callback. It is called from
53 * interrupt context when the adapter has completed the
54 * command, and wakes up anyone waiting on the command.
57 ips_wakeup_callback(ips_command_t *command)
59 bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap,
60 BUS_DMASYNC_POSTWRITE);
61 command->completed = 1;
62 wakeup(&command->completed);
66 * Below are a series of functions for sending an IO request
67 * to the adapter. The flow order is: start, send, callback, finish.
68 * The caller must have already assembled an iorequest struct to hold
69 * the details of the IO request.
72 ips_io_request_finish(ips_command_t *command)
74 struct bio *iobuf = command->arg;
76 if (ips_read_request(iobuf)) {
77 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
78 BUS_DMASYNC_POSTREAD);
80 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
81 BUS_DMASYNC_POSTWRITE);
83 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
84 if (COMMAND_ERROR(&command->status)) {
85 iobuf->bio_flags |=BIO_ERROR;
86 iobuf->bio_error = EIO;
88 ips_insert_free_cmd(command->sc, command);
93 ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments, int segnum,
97 ips_command_t *command = cmdptr;
98 ips_sg_element_t *sg_list;
99 ips_io_cmd *command_struct;
100 struct bio *iobuf = command->arg;
106 printf("ips: error = %d in ips_sg_request_callback\n", error);
107 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
108 iobuf->bio_flags |= BIO_ERROR;
109 iobuf->bio_error = ENOMEM;
110 ips_insert_free_cmd(sc, command);
114 command_struct = (ips_io_cmd *)command->command_buffer;
115 command_struct->id = command->id;
116 command_struct->drivenum = (uintptr_t)iobuf->bio_driver1;
118 if (ips_read_request(iobuf))
119 cmdtype = IPS_SG_READ_CMD;
121 cmdtype = IPS_SG_WRITE_CMD;
122 command_struct->segnum = segnum;
123 sg_list = (ips_sg_element_t *)((u_int8_t *)
124 command->command_buffer + IPS_COMMAND_LEN);
125 for (i = 0; i < segnum; i++) {
126 sg_list[i].addr = segments[i].ds_addr;
127 sg_list[i].len = segments[i].ds_len;
128 length += segments[i].ds_len;
130 command_struct->buffaddr =
131 (u_int32_t)command->command_phys_addr + IPS_COMMAND_LEN;
133 if (ips_read_request(iobuf))
134 cmdtype = IPS_READ_CMD;
136 cmdtype = IPS_WRITE_CMD;
137 command_struct->buffaddr = segments[0].ds_addr;
138 length = segments[0].ds_len;
140 command_struct->command = cmdtype;
141 command_struct->lba = iobuf->bio_pblkno;
142 length = (length + IPS_BLKSIZE - 1)/IPS_BLKSIZE;
143 command_struct->length = length;
144 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
145 BUS_DMASYNC_PREWRITE);
146 if (ips_read_request(iobuf)) {
147 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
148 BUS_DMASYNC_PREREAD);
150 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
151 BUS_DMASYNC_PREWRITE);
154 * the cast to long long below is necessary because our b_pblkno
155 * is 32bit wide whereas it's 64bit on FreeBSD-CURRENT.
157 PRINTF(10, "ips test: command id: %d segments: %d "
158 "pblkno: %lld length: %d, ds_len: %d\n", command->id, segnum,
159 (long long)iobuf->bio_pblkno,
160 length, segments[0].ds_len);
162 sc->ips_issue_cmd(command);
167 ips_send_io_request(ips_command_t *command, struct buf *iobuf)
169 command->callback = ips_io_request_finish;
170 command->arg = iobuf;
171 PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount);
172 bus_dmamap_load(command->data_dmatag, command->data_dmamap,
173 iobuf->bio_data, iobuf->bio_bcount,
174 ips_io_request_callback, command, 0);
179 ips_start_io_request(ips_softc_t *sc)
181 ips_command_t *command;
184 iobuf = bufq_first(&sc->queue);
187 if (ips_get_free_cmd(sc, &command, 0) != 0)
189 bufq_remove(&sc->queue, iobuf);
190 ips_send_io_request(command, iobuf);
194 * Below are a series of functions for sending an adapter info request
195 * to the adapter. The flow order is: get, send, callback. It uses
196 * the generic finish callback at the top of this file.
197 * This can be used to get configuration/status info from the card
200 ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum,
204 ips_command_t *command = cmdptr;
205 ips_adapter_info_cmd *command_struct;
208 command->status.value = IPS_ERROR_STATUS; /* a lovely error value */
209 ips_insert_free_cmd(sc, command);
210 printf("ips: error = %d in ips_get_adapter_info\n", error);
213 command_struct = (ips_adapter_info_cmd *)command->command_buffer;
214 command_struct->command = IPS_ADAPTER_INFO_CMD;
215 command_struct->id = command->id;
216 command_struct->buffaddr = segments[0].ds_addr;
218 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
219 BUS_DMASYNC_PREWRITE);
220 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
221 BUS_DMASYNC_PREREAD);
222 sc->ips_issue_cmd(command);
226 ips_send_adapter_info_cmd(ips_command_t *command)
228 ips_softc_t *sc = command->sc;
231 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
234 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
235 /* highaddr */ BUS_SPACE_MAXADDR,
237 /* filterarg */ NULL,
238 /* maxsize */ IPS_ADAPTER_INFO_LEN,
240 /* maxsegsize*/ IPS_ADAPTER_INFO_LEN,
242 &command->data_dmatag) != 0) {
243 printf("ips: can't alloc dma tag for adapter status\n");
247 if (bus_dmamem_alloc(command->data_dmatag, &command->data_buffer,
248 BUS_DMA_NOWAIT, &command->data_dmamap)) {
252 command->callback = ips_wakeup_callback;
253 bus_dmamap_load(command->data_dmatag, command->data_dmamap,
254 command->data_buffer, IPS_ADAPTER_INFO_LEN,
255 ips_adapter_info_callback, command, BUS_DMA_NOWAIT);
256 if ((command->status.value == IPS_ERROR_STATUS) ||
257 ips_timed_wait(command, "ips", 30 * hz) != 0)
260 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
261 BUS_DMASYNC_POSTREAD);
262 memcpy(&(sc->adapter_info), command->data_buffer,
263 IPS_ADAPTER_INFO_LEN);
265 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
267 /* I suppose I should clean up my memory allocations */
268 bus_dmamem_free(command->data_dmatag, command->data_buffer,
269 command->data_dmamap);
270 bus_dma_tag_destroy(command->data_dmatag);
271 ips_insert_free_cmd(sc, command);
276 ips_get_adapter_info(ips_softc_t *sc)
278 ips_command_t *command;
281 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
282 device_printf(sc->dev, "unable to get adapter configuration\n");
285 ips_send_adapter_info_cmd(command);
286 if (COMMAND_ERROR(&command->status))
292 * Below are a series of functions for sending a drive info request
293 * to the adapter. The flow order is: get, send, callback. It uses
294 * the generic finish callback at the top of this file.
295 * This can be used to get drive status info from the card
298 ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments, int segnum,
302 ips_command_t *command = cmdptr;
303 ips_drive_cmd *command_struct;
308 command->status.value = IPS_ERROR_STATUS;
309 ips_insert_free_cmd(sc, command);
310 printf("ips: error = %d in ips_get_drive_info\n", error);
313 command_struct = (ips_drive_cmd *)command->command_buffer;
314 command_struct->command = IPS_DRIVE_INFO_CMD;
315 command_struct->id = command->id;
316 command_struct->buffaddr = segments[0].ds_addr;
317 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
318 BUS_DMASYNC_PREWRITE);
319 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
320 BUS_DMASYNC_PREREAD);
321 sc->ips_issue_cmd(command);
325 ips_send_drive_info_cmd(ips_command_t *command)
328 ips_softc_t *sc = command->sc;
329 ips_drive_info_t *driveinfo;
331 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
334 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
335 /* highaddr */ BUS_SPACE_MAXADDR,
337 /* filterarg */ NULL,
338 /* maxsize */ IPS_DRIVE_INFO_LEN,
340 /* maxsegsize*/ IPS_DRIVE_INFO_LEN,
342 &command->data_dmatag) != 0) {
343 printf("ips: can't alloc dma tag for drive status\n");
347 if (bus_dmamem_alloc(command->data_dmatag, &command->data_buffer,
348 BUS_DMA_NOWAIT, &command->data_dmamap)) {
352 command->callback = ips_wakeup_callback;
353 bus_dmamap_load(command->data_dmatag, command->data_dmamap,
354 command->data_buffer,IPS_DRIVE_INFO_LEN,
355 ips_drive_info_callback, command, BUS_DMA_NOWAIT);
356 if ((command->status.value == IPS_ERROR_STATUS) ||
357 ips_timed_wait(command, "ips", 10 * hz) != 0)
361 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
362 BUS_DMASYNC_POSTREAD);
363 driveinfo = command->data_buffer;
364 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8);
365 sc->drivecount = driveinfo->drivecount;
366 device_printf(sc->dev, "logical drives: %d\n", sc->drivecount);
368 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
370 /* I suppose I should clean up my memory allocations */
371 bus_dmamem_free(command->data_dmatag, command->data_buffer,
372 command->data_dmamap);
373 bus_dma_tag_destroy(command->data_dmatag);
374 ips_insert_free_cmd(sc, command);
379 ips_get_drive_info(ips_softc_t *sc)
382 ips_command_t *command;
384 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
385 device_printf(sc->dev, "unable to get drive configuration\n");
388 ips_send_drive_info_cmd(command);
389 if (COMMAND_ERROR(&command->status))
395 * Below is a pair of functions for making sure data is safely
396 * on disk by flushing the adapter's cache.
399 ips_send_flush_cache_cmd(ips_command_t *command)
401 ips_softc_t *sc = command->sc;
402 ips_generic_cmd *command_struct;
404 PRINTF(10,"ips test: got a command, building flush command\n");
405 command->callback = ips_wakeup_callback;
406 command_struct = (ips_generic_cmd *)command->command_buffer;
407 command_struct->command = IPS_CACHE_FLUSH_CMD;
408 command_struct->id = command->id;
409 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
410 BUS_DMASYNC_PREWRITE);
411 sc->ips_issue_cmd(command);
412 if (command->status.value != IPS_ERROR_STATUS)
413 ips_timed_wait(command, "flush2", 0);
414 ips_insert_free_cmd(sc, command);
419 ips_flush_cache(ips_softc_t *sc)
421 ips_command_t *command;
423 device_printf(sc->dev, "flushing cache\n");
424 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
425 device_printf(sc->dev, "ERROR: unable to get a command! "
426 "can't flush cache!\n");
429 ips_send_flush_cache_cmd(command);
430 if (COMMAND_ERROR(&command->status)) {
431 device_printf(sc->dev, "ERROR: cache flush command failed!\n");
438 * Simplified localtime to provide timevalues for ffdc.
439 * Taken from libc/stdtime/localtime.c
442 ips_ffdc_settime(ips_adapter_ffdc_cmd *command, time_t sctime)
445 int yleap, *ip, month;
446 int year_lengths[2] = { IPS_DAYSPERNYEAR, IPS_DAYSPERLYEAR };
447 int mon_lengths[2][IPS_MONSPERYEAR] = {
448 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
449 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
452 days = sctime / IPS_SECSPERDAY;
453 rem = sctime % IPS_SECSPERDAY;
455 command->hour = rem / IPS_SECSPERHOUR;
456 rem = rem % IPS_SECSPERHOUR;
458 command->minute = rem / IPS_SECSPERMIN;
459 command->second = rem % IPS_SECSPERMIN;
462 while (days < 0 || days >= (long)year_lengths[yleap = ips_isleap(y)]) {
465 newy = y + days / IPS_DAYSPERNYEAR;
468 days -= (newy - y) * IPS_DAYSPERNYEAR +
469 IPS_LEAPS_THRU_END_OF(newy - 1) -
470 IPS_LEAPS_THRU_END_OF(y - 1);
473 command->yearH = y / 100;
474 command->yearL = y % 100;
475 ip = mon_lengths[yleap];
476 for (month = 0; days >= (long)ip[month]; ++month)
477 days = days - (long)ip[month];
478 command->month = month + 1;
479 command->day = days + 1;
483 ips_send_ffdc_reset_cmd(ips_command_t *command)
485 ips_softc_t *sc = command->sc;
486 ips_adapter_ffdc_cmd *command_struct;
488 PRINTF(10, "ips test: got a command, building ffdc reset command\n");
489 command->callback = ips_wakeup_callback;
490 command_struct = (ips_adapter_ffdc_cmd *)command->command_buffer;
491 command_struct->command = IPS_FFDC_CMD;
492 command_struct->id = command->id;
493 command_struct->reset_count = sc->ffdc_resetcount;
494 command_struct->reset_type = 0x0;
495 ips_ffdc_settime(command_struct, sc->ffdc_resettime.tv_sec);
496 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
497 BUS_DMASYNC_PREWRITE);
498 sc->ips_issue_cmd(command);
499 if (command->status.value != IPS_ERROR_STATUS)
500 ips_timed_wait(command, "ffdc", 0);
501 ips_insert_free_cmd(sc, command);
506 ips_ffdc_reset(ips_softc_t *sc)
508 ips_command_t *command;
510 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
511 device_printf(sc->dev, "ERROR: unable to get a command! "
512 "can't send ffdc reset!\n");
515 ips_send_ffdc_reset_cmd(command);
516 if (COMMAND_ERROR(&command->status)) {
517 device_printf(sc->dev, "ERROR: ffdc reset command failed!\n");
524 ips_write_nvram(ips_command_t *command)
526 ips_softc_t *sc = command->sc;
527 ips_rw_nvram_cmd *command_struct;
528 ips_nvram_page5 *nvram;
530 /*FIXME check for error */
531 command->callback = ips_wakeup_callback;
532 command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
533 command_struct->command = IPS_RW_NVRAM_CMD;
534 command_struct->id = command->id;
535 command_struct->pagenum = 5;
536 command_struct->rw = 1; /* write */
537 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
538 BUS_DMASYNC_POSTREAD);
539 nvram = command->data_buffer;
540 /* retrieve adapter info and save in sc */
541 sc->adapter_type = nvram->adapter_type;
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);
551 ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments, int segnum,
555 ips_command_t *command = cmdptr;
556 ips_rw_nvram_cmd *command_struct;
560 command->status.value = IPS_ERROR_STATUS;
561 ips_insert_free_cmd(sc, command);
562 printf("ips: error = %d in ips_read_nvram_callback\n", error);
565 command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
566 command_struct->command = IPS_RW_NVRAM_CMD;
567 command_struct->id = command->id;
568 command_struct->pagenum = 5;
569 command_struct->rw = 0;
570 command_struct->buffaddr = segments[0].ds_addr;
572 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
573 BUS_DMASYNC_PREWRITE);
574 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
575 BUS_DMASYNC_PREREAD);
576 sc->ips_issue_cmd(command);
580 ips_read_nvram(ips_command_t *command)
583 ips_softc_t *sc = command->sc;
585 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
588 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
589 /* highaddr */ BUS_SPACE_MAXADDR,
591 /* filterarg */ NULL,
592 /* maxsize */ IPS_NVRAM_PAGE_SIZE,
594 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE,
596 &command->data_dmatag) != 0) {
597 printf("ips: can't alloc dma tag for nvram\n");
601 if (bus_dmamem_alloc(command->data_dmatag, &command->data_buffer,
602 BUS_DMA_NOWAIT, &command->data_dmamap)) {
606 command->callback = ips_write_nvram;
607 bus_dmamap_load(command->data_dmatag, command->data_dmamap,
608 command->data_buffer, IPS_NVRAM_PAGE_SIZE, ips_read_nvram_callback,
609 command, BUS_DMA_NOWAIT);
610 if ((command->status.value == IPS_ERROR_STATUS) ||
611 ips_timed_wait(command, "ips", 0) != 0)
614 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
615 BUS_DMASYNC_POSTWRITE);
617 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
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);
627 ips_update_nvram(ips_softc_t *sc)
629 ips_command_t *command;
631 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
632 device_printf(sc->dev, "ERROR: unable to get a command! "
633 "can't update nvram\n");
636 ips_read_nvram(command);
637 if (COMMAND_ERROR(&command->status)) {
638 device_printf(sc->dev, "ERROR: nvram update command failed!\n");
645 ips_send_config_sync_cmd(ips_command_t *command)
647 ips_softc_t *sc = command->sc;
648 ips_generic_cmd *command_struct;
650 PRINTF(10, "ips test: got a command, building flush command\n");
651 command->callback = ips_wakeup_callback;
652 command_struct = (ips_generic_cmd *)command->command_buffer;
653 command_struct->command = IPS_CONFIG_SYNC_CMD;
654 command_struct->id = command->id;
655 command_struct->reserve2 = IPS_POCL;
656 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
657 BUS_DMASYNC_PREWRITE);
658 sc->ips_issue_cmd(command);
659 if (command->status.value != IPS_ERROR_STATUS)
660 ips_timed_wait(command, "ipssyn", 0);
661 ips_insert_free_cmd(sc, command);
666 ips_send_error_table_cmd(ips_command_t *command)
668 ips_softc_t *sc = command->sc;
669 ips_generic_cmd *command_struct;
671 PRINTF(10, "ips test: got a command, building errortable command\n");
672 command->callback = ips_wakeup_callback;
673 command_struct = (ips_generic_cmd *)command->command_buffer;
674 command_struct->command = IPS_ERROR_TABLE_CMD;
675 command_struct->id = command->id;
676 command_struct->reserve2 = IPS_CSL;
677 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
678 BUS_DMASYNC_PREWRITE);
679 sc->ips_issue_cmd(command);
680 if (command->status.value != IPS_ERROR_STATUS)
681 ips_timed_wait(command, "ipsetc", 0);
682 ips_insert_free_cmd(sc, command);
687 ips_clear_adapter(ips_softc_t *sc)
689 ips_command_t *command;
691 device_printf(sc->dev, "syncing config\n");
692 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
693 device_printf(sc->dev, "ERROR: unable to get a command! "
694 "can't sync cache!\n");
697 ips_send_config_sync_cmd(command);
698 if (COMMAND_ERROR(&command->status)) {
699 device_printf(sc->dev, "ERROR: cache sync command failed!\n");
702 device_printf(sc->dev, "clearing error table\n");
703 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
704 device_printf(sc->dev, "ERROR: unable to get a command! "
705 "can't sync cache!\n");
708 ips_send_error_table_cmd(command);
709 if (COMMAND_ERROR(&command->status)) {
710 device_printf(sc->dev, "ERROR: etable command failed!\n");