FreeBSD/Linux Kernel Cross Reference
sys/dev/ips/ips.c
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$");
30
31 #include <dev/ips/ipsreg.h>
32 #include <dev/ips/ips.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35
36 static d_open_t ips_open;
37 static d_close_t ips_close;
38 static d_ioctl_t ips_ioctl;
39
40 MALLOC_DEFINE(M_IPSBUF, "ipsbuf","IPS driver buffer");
41
42 static struct cdevsw ips_cdevsw = {
43 .d_version = D_VERSION,
44 .d_flags = D_NEEDGIANT,
45 .d_open = ips_open,
46 .d_close = ips_close,
47 .d_ioctl = ips_ioctl,
48 .d_name = "ips",
49 };
50
51 static const char* ips_adapter_name[] = {
52 "N/A",
53 "ServeRAID (copperhead)",
54 "ServeRAID II (copperhead refresh)",
55 "ServeRAID onboard (copperhead)",
56 "ServeRAID onboard (copperhead)",
57 "ServeRAID 3H (clarinet)",
58 "ServeRAID 3L (clarinet lite)",
59 "ServeRAID 4H (trombone)",
60 "ServeRAID 4M (morpheus)",
61 "ServeRAID 4L (morpheus lite)",
62 "ServeRAID 4Mx (neo)",
63 "ServeRAID 4Lx (neo lite)",
64 "ServeRAID 5i II (sarasota)",
65 "ServeRAID 5i (sarasota)",
66 "ServeRAID 6M (marco)",
67 "ServeRAID 6i (sebring)",
68 "ServeRAID 7t",
69 "ServeRAID 7k",
70 "ServeRAID 7M"
71 };
72
73
74 static int ips_open(struct cdev *dev, int flags, int fmt, struct thread *td)
75 {
76 ips_softc_t *sc = dev->si_drv1;
77 sc->state |= IPS_DEV_OPEN;
78 return 0;
79 }
80
81 static int ips_close(struct cdev *dev, int flags, int fmt, struct thread *td)
82 {
83 ips_softc_t *sc = dev->si_drv1;
84 sc->state &= ~IPS_DEV_OPEN;
85
86 return 0;
87 }
88
89 static int ips_ioctl(struct cdev *dev, u_long command, caddr_t addr, int32_t flags, struct thread *td)
90 {
91 ips_softc_t *sc;
92
93 sc = dev->si_drv1;
94 return ips_ioctl_request(sc, command, addr, flags);
95 }
96
97 static void ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
98 {
99 ips_command_t *command = cmdptr;
100 PRINTF(10, "ips: in ips_cmd_dmaload\n");
101 if(!error)
102 command->command_phys_addr = segments[0].ds_addr;
103
104 }
105
106 /* is locking needed? what locking guarentees are there on removal? */
107 static int ips_cmdqueue_free(ips_softc_t *sc)
108 {
109 int i, error = -1;
110 ips_command_t *command;
111
112 if(!sc->used_commands){
113 for(i = 0; i < sc->max_cmds; i++){
114
115 command = &sc->commandarray[i];
116
117 if(command->command_phys_addr == 0)
118 continue;
119 bus_dmamap_unload(sc->command_dmatag,
120 command->command_dmamap);
121 bus_dmamem_free(sc->command_dmatag,
122 command->command_buffer,
123 command->command_dmamap);
124 if (command->data_dmamap != NULL)
125 bus_dmamap_destroy(command->data_dmatag,
126 command->data_dmamap);
127 }
128 error = 0;
129 sc->state |= IPS_OFFLINE;
130 }
131 sc->staticcmd = NULL;
132 free(sc->commandarray, M_DEVBUF);
133 return error;
134 }
135
136 /* places all ips command structs on the free command queue. No locking as if someone else tries
137 * to access this during init, we have bigger problems */
138 static int ips_cmdqueue_init(ips_softc_t *sc)
139 {
140 int i;
141 ips_command_t *command;
142
143 sc->commandarray = (ips_command_t *)malloc(sizeof(ips_command_t) *
144 sc->max_cmds, M_DEVBUF, M_NOWAIT|M_ZERO);
145 if (sc->commandarray == NULL)
146 return (ENOMEM);
147
148 SLIST_INIT(&sc->free_cmd_list);
149 for(i = 0; i < sc->max_cmds; i++){
150 command = &sc->commandarray[i];
151 command->id = i;
152 command->sc = sc;
153
154 if(bus_dmamem_alloc(sc->command_dmatag,&command->command_buffer,
155 BUS_DMA_NOWAIT, &command->command_dmamap))
156 goto error;
157 bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
158 command->command_buffer,IPS_COMMAND_LEN,
159 ips_cmd_dmaload, command, BUS_DMA_NOWAIT);
160 if(!command->command_phys_addr){
161 bus_dmamem_free(sc->command_dmatag,
162 command->command_buffer, command->command_dmamap);
163 goto error;
164 }
165
166 if (i != 0) {
167 command->data_dmatag = sc->sg_dmatag;
168 if (bus_dmamap_create(command->data_dmatag, 0,
169 &command->data_dmamap))
170 goto error;
171 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
172 } else
173 sc->staticcmd = command;
174 }
175 sc->state &= ~IPS_OFFLINE;
176 return 0;
177 error:
178 ips_cmdqueue_free(sc);
179 return ENOMEM;
180 }
181
182 /* returns a free command struct if one is available.
183 * It also blanks out anything that may be a wild pointer/value.
184 * Also, command buffers are not freed. They are
185 * small so they are saved and kept dmamapped and loaded.
186 */
187 int ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags)
188 {
189 ips_command_t *command;
190
191 if(sc->state & IPS_OFFLINE){
192 return EIO;
193 }
194 if ((flags & IPS_STATIC_FLAG) == 0) {
195 command = SLIST_FIRST(&sc->free_cmd_list);
196 if(!command || (sc->state & IPS_TIMEOUT)){
197 return EBUSY;
198 }
199 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
200 (sc->used_commands)++;
201 } else {
202 if (sc->state & IPS_STATIC_BUSY)
203 return EAGAIN;
204 command = sc->staticcmd;
205 sc->state |= IPS_STATIC_BUSY;
206 }
207 clear_ips_command(command);
208 bzero(command->command_buffer, IPS_COMMAND_LEN);
209 *cmd = command;
210 return 0;
211 }
212
213 /* adds a command back to the free command queue */
214 void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
215 {
216
217 if (sema_value(&sc->cmd_sema) != 0)
218 panic("ips: command returned non-zero semaphore");
219
220 if (command != sc->staticcmd) {
221 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
222 (sc->used_commands)--;
223 } else {
224 sc->state &= ~IPS_STATIC_BUSY;
225 }
226 }
227 static const char* ips_diskdev_statename(u_int8_t state)
228 {
229 static char statebuf[20];
230 switch(state){
231 case IPS_LD_OFFLINE:
232 return("OFFLINE");
233 break;
234 case IPS_LD_OKAY:
235 return("OK");
236 break;
237 case IPS_LD_DEGRADED:
238 return("DEGRADED");
239 break;
240 case IPS_LD_FREE:
241 return("FREE");
242 break;
243 case IPS_LD_SYS:
244 return("SYS");
245 break;
246 case IPS_LD_CRS:
247 return("CRS");
248 break;
249 }
250 sprintf(statebuf,"UNKNOWN(0x%02x)", state);
251 return(statebuf);
252 }
253
254 static int ips_diskdev_init(ips_softc_t *sc)
255 {
256 int i;
257 for(i=0; i < IPS_MAX_NUM_DRIVES; i++){
258 if(sc->drives[i].state == IPS_LD_FREE) continue;
259 device_printf(sc->dev, "Logical Drive %d: RAID%d sectors: %u, state %s\n",
260 i, sc->drives[i].raid_lvl,
261 sc->drives[i].sector_count,
262 ips_diskdev_statename(sc->drives[i].state));
263 if(sc->drives[i].state == IPS_LD_OKAY ||
264 sc->drives[i].state == IPS_LD_DEGRADED){
265 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
266 device_set_ivars(sc->diskdev[i],(void *)(uintptr_t) i);
267 }
268 }
269 if(bus_generic_attach(sc->dev)){
270 device_printf(sc->dev, "Attaching bus failed\n");
271 }
272 return 0;
273 }
274
275 static int ips_diskdev_free(ips_softc_t *sc)
276 {
277 int i;
278 int error = 0;
279 for(i = 0; i < IPS_MAX_NUM_DRIVES; i++){
280 if(sc->diskdev[i])
281 error = device_delete_child(sc->dev, sc->diskdev[i]);
282 if(error)
283 return error;
284 }
285 bus_generic_detach(sc->dev);
286 return 0;
287 }
288
289 /* ips_timeout is periodically called to make sure no commands sent
290 * to the card have become stuck. If it finds a stuck command, it
291 * sets a flag so the driver won't start any more commands and then
292 * is periodically called to see if all outstanding commands have
293 * either finished or timed out. Once timed out, an attempt to
294 * reinitialize the card is made. If that fails, the driver gives
295 * up and declares the card dead. */
296 static void ips_timeout(void *arg)
297 {
298 ips_softc_t *sc = arg;
299 int i, state = 0;
300 ips_command_t *command;
301
302 mtx_lock(&sc->queue_mtx);
303 command = &sc->commandarray[0];
304 for(i = 0; i < sc->max_cmds; i++){
305 if(!command[i].timeout){
306 continue;
307 }
308 command[i].timeout--;
309 if(!command[i].timeout){
310 if(!(sc->state & IPS_TIMEOUT)){
311 sc->state |= IPS_TIMEOUT;
312 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
313 }
314 ips_set_error(&command[i], ETIMEDOUT);
315 command[i].callback(&command[i]);
316 /* hmm, this should be enough cleanup */
317 } else
318 state = 1;
319 }
320 if(!state && (sc->state & IPS_TIMEOUT)){
321 if(sc->ips_adapter_reinit(sc, 1)){
322 device_printf(sc->dev, "AIEE! adapter reset failed, giving up and going home! Have a nice day.\n");
323 sc->state |= IPS_OFFLINE;
324 sc->state &= ~IPS_TIMEOUT;
325 /* Grr, I hate this solution. I run waiting commands
326 one at a time and error them out just before they
327 would go to the card. This sucks. */
328 } else
329 sc->state &= ~IPS_TIMEOUT;
330 }
331 if (sc->state != IPS_OFFLINE)
332 sc->timer = timeout(ips_timeout, sc, 10*hz);
333 mtx_unlock(&sc->queue_mtx);
334 }
335
336 /* check card and initialize it */
337 int ips_adapter_init(ips_softc_t *sc)
338 {
339 int i;
340 DEVICE_PRINTF(1,sc->dev, "initializing\n");
341
342 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
343 /* alignemnt */ 1,
344 /* boundary */ 0,
345 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
346 /* highaddr */ BUS_SPACE_MAXADDR,
347 /* filter */ NULL,
348 /* filterarg */ NULL,
349 /* maxsize */ IPS_COMMAND_LEN +
350 IPS_MAX_SG_LEN,
351 /* numsegs */ 1,
352 /* maxsegsize*/ IPS_COMMAND_LEN +
353 IPS_MAX_SG_LEN,
354 /* flags */ 0,
355 /* lockfunc */ NULL,
356 /* lockarg */ NULL,
357 &sc->command_dmatag) != 0) {
358 device_printf(sc->dev, "can't alloc command dma tag\n");
359 goto error;
360 }
361 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
362 /* alignemnt */ 1,
363 /* boundary */ 0,
364 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
365 /* highaddr */ BUS_SPACE_MAXADDR,
366 /* filter */ NULL,
367 /* filterarg */ NULL,
368 /* maxsize */ IPS_MAX_IOBUF_SIZE,
369 /* numsegs */ IPS_MAX_SG_ELEMENTS,
370 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
371 /* flags */ 0,
372 /* lockfunc */ busdma_lock_mutex,
373 /* lockarg */ &sc->queue_mtx,
374 &sc->sg_dmatag) != 0) {
375 device_printf(sc->dev, "can't alloc SG dma tag\n");
376 goto error;
377 }
378 /* create one command buffer until we know how many commands this card
379 can handle */
380 sc->max_cmds = 1;
381 ips_cmdqueue_init(sc);
382 callout_handle_init(&sc->timer);
383
384 if(sc->ips_adapter_reinit(sc, 0))
385 goto error;
386
387 /* initialize ffdc values */
388 microtime(&sc->ffdc_resettime);
389 sc->ffdc_resetcount = 1;
390 if ((i = ips_ffdc_reset(sc)) != 0) {
391 device_printf(sc->dev, "failed to send ffdc reset to device (%d)\n", i);
392 goto error;
393 }
394 if ((i = ips_get_adapter_info(sc)) != 0) {
395 device_printf(sc->dev, "failed to get adapter configuration data from device (%d)\n", i);
396 goto error;
397 }
398 ips_update_nvram(sc); /* no error check as failure doesn't matter */
399 if(sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T){
400 device_printf(sc->dev, "adapter type: %s\n", ips_adapter_name[sc->adapter_type]);
401 }
402 if ((i = ips_get_drive_info(sc)) != 0) {
403 device_printf(sc->dev, "failed to get drive configuration data from device (%d)\n", i);
404 goto error;
405 }
406
407 ips_cmdqueue_free(sc);
408 if(sc->adapter_info.max_concurrent_cmds)
409 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
410 else
411 sc->max_cmds = 32;
412 if(ips_cmdqueue_init(sc)){
413 device_printf(sc->dev, "failed to initialize command buffers\n");
414 goto error;
415 }
416 sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
417 S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
418 sc->device_file->si_drv1 = sc;
419 ips_diskdev_init(sc);
420 sc->timer = timeout(ips_timeout, sc, 10*hz);
421 return 0;
422
423 error:
424 ips_adapter_free(sc);
425 return ENXIO;
426 }
427
428 /* see if we should reinitialize the card and wait for it to timeout or complete initialization */
429 int ips_morpheus_reinit(ips_softc_t *sc, int force)
430 {
431 u_int32_t tmp;
432 int i;
433
434 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
435 if(!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
436 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp){
437 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
438 return 0;
439 }
440 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
441 ips_read_4(sc, MORPHEUS_REG_OIMR);
442
443 device_printf(sc->dev, "resetting adapter, this may take up to 5 minutes\n");
444 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
445 DELAY(5000000);
446 ips_read_4(sc, MORPHEUS_REG_OIMR);
447
448 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
449 for(i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++){
450 DELAY(1000000);
451 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
452 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
453 }
454 if(tmp & MORPHEUS_BIT_POST1)
455 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
456
457 if( i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK){
458 device_printf(sc->dev,"Adapter error during initialization.\n");
459 return 1;
460 }
461 for(i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++){
462 DELAY(1000000);
463 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
464 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
465 }
466 if(tmp & MORPHEUS_BIT_POST2)
467 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
468
469 if(i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)){
470 device_printf(sc->dev, "adapter failed config check\n");
471 return 1;
472 }
473 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
474 if(force && ips_clear_adapter(sc)){
475 device_printf(sc->dev, "adapter clear failed\n");
476 return 1;
477 }
478 return 0;
479 }
480
481 /* clean up so we can unload the driver. */
482 int ips_adapter_free(ips_softc_t *sc)
483 {
484 int error = 0;
485 if(sc->state & IPS_DEV_OPEN)
486 return EBUSY;
487 if((error = ips_diskdev_free(sc)))
488 return error;
489 if(ips_cmdqueue_free(sc)){
490 device_printf(sc->dev,
491 "trying to exit when command queue is not empty!\n");
492 return EBUSY;
493 }
494 DEVICE_PRINTF(1, sc->dev, "free\n");
495 untimeout(ips_timeout, sc, sc->timer);
496
497 if(sc->sg_dmatag)
498 bus_dma_tag_destroy(sc->sg_dmatag);
499 if(sc->command_dmatag)
500 bus_dma_tag_destroy(sc->command_dmatag);
501 if(sc->device_file)
502 destroy_dev(sc->device_file);
503 return 0;
504 }
505
506 static __inline int ips_morpheus_check_intr(ips_softc_t *sc)
507 {
508 int cmdnumber;
509 ips_cmd_status_t status;
510 ips_command_t *command;
511 int found = 0;
512 u_int32_t oisr;
513
514 oisr = ips_read_4(sc, MORPHEUS_REG_OISR);
515 PRINTF(9, "interrupt registers out:%x\n", oisr);
516 if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
517 DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
518 return (0);
519 }
520 while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
521 cmdnumber = status.fields.command_id;
522 command = &sc->commandarray[cmdnumber];
523 command->status.value = status.value;
524 command->timeout = 0;
525 command->callback(command);
526
527 found = 1;
528 }
529 return (found);
530 }
531
532 void ips_morpheus_intr(void *void_sc)
533 {
534 ips_softc_t *sc = void_sc;
535
536 mtx_lock(&sc->queue_mtx);
537 ips_morpheus_check_intr(sc);
538 mtx_unlock(&sc->queue_mtx);
539 }
540
541 void ips_morpheus_poll(ips_command_t *command)
542 {
543 uint32_t ts;
544
545 /*
546 * Locks are not used here because this is only called during
547 * crashdumps.
548 */
549 ts = time_second + command->timeout;
550 while ((command->timeout != 0)
551 && (ips_morpheus_check_intr(command->sc) == 0)
552 && (ts > time_second))
553 DELAY(1000);
554 }
555
556 void ips_issue_morpheus_cmd(ips_command_t *command)
557 {
558 /* hmmm, is there a cleaner way to do this? */
559 if(command->sc->state & IPS_OFFLINE){
560 ips_set_error(command, EINVAL);
561 command->callback(command);
562 return;
563 }
564 command->timeout = 10;
565 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
566 }
567
568 static void ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,int segnum, int error)
569 {
570 ips_copper_queue_t *queue = queueptr;
571 if(error){
572 return;
573 }
574 queue->base_phys_addr = segments[0].ds_addr;
575 }
576
577 static int ips_copperhead_queue_init(ips_softc_t *sc)
578 {
579 int error;
580 bus_dma_tag_t dmatag;
581 bus_dmamap_t dmamap;
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 */ sizeof(ips_copper_queue_t),
590 /* numsegs */ 1,
591 /* maxsegsize*/ sizeof(ips_copper_queue_t),
592 /* flags */ 0,
593 /* lockfunc */ NULL,
594 /* lockarg */ NULL,
595 &dmatag) != 0) {
596 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
597 error = ENOMEM;
598 goto exit;
599 }
600 if(bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
601 BUS_DMA_NOWAIT, &dmamap)){
602 error = ENOMEM;
603 goto exit;
604 }
605 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
606 sc->copper_queue->dmatag = dmatag;
607 sc->copper_queue->dmamap = dmamap;
608 sc->copper_queue->nextstatus = 1;
609 bus_dmamap_load(dmatag, dmamap,
610 &(sc->copper_queue->status[0]), IPS_MAX_CMD_NUM * 4,
611 ips_copperhead_queue_callback, sc->copper_queue,
612 BUS_DMA_NOWAIT);
613 if(sc->copper_queue->base_phys_addr == 0){
614 error = ENOMEM;
615 goto exit;
616 }
617 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
618 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
619 IPS_MAX_CMD_NUM * 4);
620 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
621 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
622
623
624 return 0;
625 exit:
626 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
627 bus_dma_tag_destroy(dmatag);
628 return error;
629 }
630
631 /* see if we should reinitialize the card and wait for it to timeout or complete initialization FIXME */
632 int ips_copperhead_reinit(ips_softc_t *sc, int force)
633 {
634 int i, j;
635 u_int32_t postcode = 0, configstatus = 0;
636 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
637 ips_write_1(sc, COPPER_REG_SCPR, 0);
638 device_printf(sc->dev, "reinitializing adapter, this could take several minutes.\n");
639 for(j = 0; j < 2; j++){
640 postcode <<= 8;
641 for(i = 0; i < 45; i++){
642 if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
643 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
644 ips_write_1(sc, COPPER_REG_HISR,
645 COPPER_GHI_BIT);
646 break;
647 } else
648 DELAY(1000000);
649 }
650 if(i == 45)
651 return 1;
652 }
653 for(j = 0; j < 2; j++){
654 configstatus <<= 8;
655 for(i = 0; i < 240; i++){
656 if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
657 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
658 ips_write_1(sc, COPPER_REG_HISR,
659 COPPER_GHI_BIT);
660 break;
661 } else
662 DELAY(1000000);
663 }
664 if(i == 240)
665 return 1;
666 }
667 for(i = 0; i < 240; i++){
668 if(!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT)){
669 break;
670 } else
671 DELAY(1000000);
672 }
673 if(i == 240)
674 return 1;
675 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
676 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
677 ips_copperhead_queue_init(sc);
678 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
679 i = ips_read_1(sc, COPPER_REG_SCPR);
680 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
681 if(!configstatus){
682 device_printf(sc->dev, "adapter initialization failed\n");
683 return 1;
684 }
685 if(force && ips_clear_adapter(sc)){
686 device_printf(sc->dev, "adapter clear failed\n");
687 return 1;
688 }
689 return 0;
690 }
691 static u_int32_t ips_copperhead_cmd_status(ips_softc_t *sc)
692 {
693 u_int32_t value;
694 int statnum = sc->copper_queue->nextstatus++;
695 if(sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
696 sc->copper_queue->nextstatus = 0;
697 value = sc->copper_queue->status[statnum];
698 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
699 4 * statnum);
700 return value;
701 }
702
703
704 void ips_copperhead_intr(void *void_sc)
705 {
706 ips_softc_t *sc = (ips_softc_t *)void_sc;
707 int cmdnumber;
708 ips_cmd_status_t status;
709
710 mtx_lock(&sc->queue_mtx);
711 while(ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT){
712 status.value = ips_copperhead_cmd_status(sc);
713 cmdnumber = status.fields.command_id;
714 sc->commandarray[cmdnumber].status.value = status.value;
715 sc->commandarray[cmdnumber].timeout = 0;
716 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
717 PRINTF(9, "ips: got command %d\n", cmdnumber);
718 }
719 mtx_unlock(&sc->queue_mtx);
720 return;
721 }
722
723 void ips_issue_copperhead_cmd(ips_command_t *command)
724 {
725 int i;
726 /* hmmm, is there a cleaner way to do this? */
727 if(command->sc->state & IPS_OFFLINE){
728 ips_set_error(command, EINVAL);
729 command->callback(command);
730 return;
731 }
732 command->timeout = 10;
733 for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
734 i++ ){
735 if( i == 20){
736 printf("sem bit still set, can't send a command\n");
737 return;
738 }
739 DELAY(500);/* need to do a delay here */
740 }
741 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
742 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
743 }
744
745 void ips_copperhead_poll(ips_command_t *command)
746 {
747
748 printf("ips: cmd polling not implemented for copperhead devices\n");
749 }
Cache object: e8fbe5b7da99f352b7248b00ed9e7cf1
|