mlx.c (b9256fe34ed4f5394392fb4cce456051bd5ef2f6) | mlx.c (da8bb3a3bf71a0579594e2faa0dd92b821689e12) |
---|---|
1/*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 26 unchanged lines hidden (view full) --- 35#include <sys/malloc.h> 36#include <sys/kernel.h> 37 38#include <sys/buf.h> 39#include <sys/bus.h> 40#include <sys/conf.h> 41#include <sys/devicestat.h> 42#include <sys/disk.h> | 1/*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 26 unchanged lines hidden (view full) --- 35#include <sys/malloc.h> 36#include <sys/kernel.h> 37 38#include <sys/buf.h> 39#include <sys/bus.h> 40#include <sys/conf.h> 41#include <sys/devicestat.h> 42#include <sys/disk.h> |
43#include <sys/stat.h> |
|
43 44#include <machine/resource.h> 45#include <machine/bus.h> 46#include <machine/clock.h> 47#include <sys/rman.h> 48 49#include <dev/mlx/mlxio.h> 50#include <dev/mlx/mlxvar.h> 51#include <dev/mlx/mlxreg.h> 52 | 44 45#include <machine/resource.h> 46#include <machine/bus.h> 47#include <machine/clock.h> 48#include <sys/rman.h> 49 50#include <dev/mlx/mlxio.h> 51#include <dev/mlx/mlxvar.h> 52#include <dev/mlx/mlxreg.h> 53 |
53#if 0 54#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args) 55#else 56#define debug(fmt, args...) 57#endif 58 | |
59#define MLX_CDEV_MAJOR 130 60 61static struct cdevsw mlx_cdevsw = { 62 /* open */ mlx_open, 63 /* close */ mlx_close, 64 /* read */ noread, 65 /* write */ nowrite, 66 /* ioctl */ mlx_ioctl, 67 /* poll */ nopoll, 68 /* mmap */ nommap, 69 /* strategy */ nostrategy, 70 /* name */ "mlx", 71 /* maj */ MLX_CDEV_MAJOR, 72 /* dump */ nodump, 73 /* psize */ nopsize, 74 /* flags */ 0, 75 /* bmaj */ -1 76}; 77 | 54#define MLX_CDEV_MAJOR 130 55 56static struct cdevsw mlx_cdevsw = { 57 /* open */ mlx_open, 58 /* close */ mlx_close, 59 /* read */ noread, 60 /* write */ nowrite, 61 /* ioctl */ mlx_ioctl, 62 /* poll */ nopoll, 63 /* mmap */ nommap, 64 /* strategy */ nostrategy, 65 /* name */ "mlx", 66 /* maj */ MLX_CDEV_MAJOR, 67 /* dump */ nodump, 68 /* psize */ nopsize, 69 /* flags */ 0, 70 /* bmaj */ -1 71}; 72 |
78static int cdev_registered = 0; | |
79devclass_t mlx_devclass; 80 81/* 82 * Per-interface accessor methods 83 */ 84static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 85static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 86static void mlx_v3_intaction(struct mlx_softc *sc, int action); | 73devclass_t mlx_devclass; 74 75/* 76 * Per-interface accessor methods 77 */ 78static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 79static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 80static void mlx_v3_intaction(struct mlx_softc *sc, int action); |
81static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); |
|
87 88static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 89static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 90static void mlx_v4_intaction(struct mlx_softc *sc, int action); | 82 83static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 84static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 85static void mlx_v4_intaction(struct mlx_softc *sc, int action); |
86static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); |
|
91 92static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 93static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 94static void mlx_v5_intaction(struct mlx_softc *sc, int action); | 87 88static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 89static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 90static void mlx_v5_intaction(struct mlx_softc *sc, int action); |
91static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); |
|
95 96/* 97 * Status monitoring 98 */ 99static void mlx_periodic(void *data); 100static void mlx_periodic_enquiry(struct mlx_command *mc); 101static void mlx_periodic_eventlog_poll(struct mlx_softc *sc); 102static void mlx_periodic_eventlog_respond(struct mlx_command *mc); --- 35 unchanged lines hidden (view full) --- 138static int mlx_done(struct mlx_softc *sc); 139static void mlx_complete(struct mlx_softc *sc); 140 141/* 142 * Debugging. 143 */ 144static char *mlx_diagnose_command(struct mlx_command *mc); 145static void mlx_describe_controller(struct mlx_softc *sc); | 92 93/* 94 * Status monitoring 95 */ 96static void mlx_periodic(void *data); 97static void mlx_periodic_enquiry(struct mlx_command *mc); 98static void mlx_periodic_eventlog_poll(struct mlx_softc *sc); 99static void mlx_periodic_eventlog_respond(struct mlx_command *mc); --- 35 unchanged lines hidden (view full) --- 135static int mlx_done(struct mlx_softc *sc); 136static void mlx_complete(struct mlx_softc *sc); 137 138/* 139 * Debugging. 140 */ 141static char *mlx_diagnose_command(struct mlx_command *mc); 142static void mlx_describe_controller(struct mlx_softc *sc); |
143static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2); |
|
146 | 144 |
147 | |
148/* 149 * Utility functions. 150 */ 151static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit); 152 153/******************************************************************************** 154 ******************************************************************************** 155 Public Interfaces --- 5 unchanged lines hidden (view full) --- 161 * 162 * Should not be called if the controller is active. 163 */ 164void 165mlx_free(struct mlx_softc *sc) 166{ 167 struct mlx_command *mc; 168 | 145/* 146 * Utility functions. 147 */ 148static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit); 149 150/******************************************************************************** 151 ******************************************************************************** 152 Public Interfaces --- 5 unchanged lines hidden (view full) --- 158 * 159 * Should not be called if the controller is active. 160 */ 161void 162mlx_free(struct mlx_softc *sc) 163{ 164 struct mlx_command *mc; 165 |
169 debug("called"); | 166 debug_called(1); |
170 171 /* cancel status timeout */ 172 untimeout(mlx_periodic, sc, sc->mlx_timeout); 173 174 /* throw away any command buffers */ 175 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) { 176 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 177 mlx_freecmd(mc); --- 22 unchanged lines hidden (view full) --- 200 /* release the register window mapping */ 201 if (sc->mlx_mem != NULL) 202 bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY, 203 (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem); 204 205 /* free controller enquiry data */ 206 if (sc->mlx_enq2 != NULL) 207 free(sc->mlx_enq2, M_DEVBUF); | 167 168 /* cancel status timeout */ 169 untimeout(mlx_periodic, sc, sc->mlx_timeout); 170 171 /* throw away any command buffers */ 172 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) { 173 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 174 mlx_freecmd(mc); --- 22 unchanged lines hidden (view full) --- 197 /* release the register window mapping */ 198 if (sc->mlx_mem != NULL) 199 bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY, 200 (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem); 201 202 /* free controller enquiry data */ 203 if (sc->mlx_enq2 != NULL) 204 free(sc->mlx_enq2, M_DEVBUF); |
205 206 /* destroy control device */ 207 if (sc->mlx_dev_t != (dev_t)NULL) 208 destroy_dev(sc->mlx_dev_t); |
|
208} 209 210/******************************************************************************** 211 * Map the scatter/gather table into bus space 212 */ 213static void 214mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 215{ 216 struct mlx_softc *sc = (struct mlx_softc *)arg; 217 | 209} 210 211/******************************************************************************** 212 * Map the scatter/gather table into bus space 213 */ 214static void 215mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 216{ 217 struct mlx_softc *sc = (struct mlx_softc *)arg; 218 |
218 debug("called"); | 219 debug_called(1); |
219 220 /* save base of s/g table's address in bus space */ 221 sc->mlx_sgbusaddr = segs->ds_addr; 222} 223 224static int 225mlx_sglist_map(struct mlx_softc *sc) 226{ 227 size_t segsize; 228 int error; 229 | 220 221 /* save base of s/g table's address in bus space */ 222 sc->mlx_sgbusaddr = segs->ds_addr; 223} 224 225static int 226mlx_sglist_map(struct mlx_softc *sc) 227{ 228 size_t segsize; 229 int error; 230 |
230 debug("called"); | 231 debug_called(1); |
231 232 /* destroy any existing mappings */ 233 if (sc->mlx_sgtable) 234 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap); 235 if (sc->mlx_sg_dmat) 236 bus_dma_tag_destroy(sc->mlx_sg_dmat); 237 238 /* 239 * Create a single tag describing a region large enough to hold all of 240 * the s/g lists we will need. 241 */ | 232 233 /* destroy any existing mappings */ 234 if (sc->mlx_sgtable) 235 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap); 236 if (sc->mlx_sg_dmat) 237 bus_dma_tag_destroy(sc->mlx_sg_dmat); 238 239 /* 240 * Create a single tag describing a region large enough to hold all of 241 * the s/g lists we will need. 242 */ |
242 segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * sc->mlx_maxiop; | 243 segsize = sizeof(struct mlx_sgentry) * sc->mlx_sg_nseg * sc->mlx_maxiop; |
243 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 244 1, 0, /* alignment, boundary */ 245 BUS_SPACE_MAXADDR, /* lowaddr */ 246 BUS_SPACE_MAXADDR, /* highaddr */ 247 NULL, NULL, /* filter, filterarg */ 248 segsize, 1, /* maxsize, nsegments */ 249 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 250 0, /* flags */ --- 21 unchanged lines hidden (view full) --- 272} 273 274/******************************************************************************** 275 * Initialise the controller and softc 276 */ 277int 278mlx_attach(struct mlx_softc *sc) 279{ | 244 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 245 1, 0, /* alignment, boundary */ 246 BUS_SPACE_MAXADDR, /* lowaddr */ 247 BUS_SPACE_MAXADDR, /* highaddr */ 248 NULL, NULL, /* filter, filterarg */ 249 segsize, 1, /* maxsize, nsegments */ 250 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 251 0, /* flags */ --- 21 unchanged lines hidden (view full) --- 273} 274 275/******************************************************************************** 276 * Initialise the controller and softc 277 */ 278int 279mlx_attach(struct mlx_softc *sc) 280{ |
280 int rid, error, fwminor; | 281 struct mlx_enquiry_old *meo; 282 int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg; |
281 | 283 |
282 debug("called"); | 284 debug_called(1); |
283 284 /* 285 * Initialise per-controller queues. 286 */ 287 TAILQ_INIT(&sc->mlx_work); 288 TAILQ_INIT(&sc->mlx_freecmds); 289 bufq_init(&sc->mlx_bufq); 290 291 /* 292 * Select accessor methods based on controller interface type. 293 */ 294 switch(sc->mlx_iftype) { | 285 286 /* 287 * Initialise per-controller queues. 288 */ 289 TAILQ_INIT(&sc->mlx_work); 290 TAILQ_INIT(&sc->mlx_freecmds); 291 bufq_init(&sc->mlx_bufq); 292 293 /* 294 * Select accessor methods based on controller interface type. 295 */ 296 switch(sc->mlx_iftype) { |
297 case MLX_IFTYPE_2: |
|
295 case MLX_IFTYPE_3: 296 sc->mlx_tryqueue = mlx_v3_tryqueue; 297 sc->mlx_findcomplete = mlx_v3_findcomplete; 298 sc->mlx_intaction = mlx_v3_intaction; | 298 case MLX_IFTYPE_3: 299 sc->mlx_tryqueue = mlx_v3_tryqueue; 300 sc->mlx_findcomplete = mlx_v3_findcomplete; 301 sc->mlx_intaction = mlx_v3_intaction; |
302 sc->mlx_fw_handshake = mlx_v3_fw_handshake; 303 sc->mlx_sg_nseg = MLX_NSEG_OLD; |
|
299 break; 300 case MLX_IFTYPE_4: 301 sc->mlx_tryqueue = mlx_v4_tryqueue; 302 sc->mlx_findcomplete = mlx_v4_findcomplete; 303 sc->mlx_intaction = mlx_v4_intaction; | 304 break; 305 case MLX_IFTYPE_4: 306 sc->mlx_tryqueue = mlx_v4_tryqueue; 307 sc->mlx_findcomplete = mlx_v4_findcomplete; 308 sc->mlx_intaction = mlx_v4_intaction; |
309 sc->mlx_fw_handshake = mlx_v4_fw_handshake; 310 sc->mlx_sg_nseg = MLX_NSEG_NEW; |
|
304 break; 305 case MLX_IFTYPE_5: 306 sc->mlx_tryqueue = mlx_v5_tryqueue; 307 sc->mlx_findcomplete = mlx_v5_findcomplete; 308 sc->mlx_intaction = mlx_v5_intaction; | 311 break; 312 case MLX_IFTYPE_5: 313 sc->mlx_tryqueue = mlx_v5_tryqueue; 314 sc->mlx_findcomplete = mlx_v5_findcomplete; 315 sc->mlx_intaction = mlx_v5_intaction; |
316 sc->mlx_fw_handshake = mlx_v5_fw_handshake; 317 sc->mlx_sg_nseg = MLX_NSEG_NEW; |
|
309 break; 310 default: 311 device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype); 312 return(ENXIO); /* should never happen */ 313 } 314 315 /* disable interrupts before we start talking to the controller */ 316 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 317 318 /* | 318 break; 319 default: 320 device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype); 321 return(ENXIO); /* should never happen */ 322 } 323 324 /* disable interrupts before we start talking to the controller */ 325 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 326 327 /* |
328 * Wait for the controller to come ready, handshake with the firmware if required. 329 * This is typically only necessary on platforms where the controller BIOS does not 330 * run. 331 */ 332 hsmsg = 0; 333 DELAY(1000); 334 while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) { 335 /* report first time around... */ 336 if (hsmsg == 0) { 337 device_printf(sc->mlx_dev, "controller initialisation in progress...\n"); 338 hsmsg = 1; 339 } 340 /* did we get a real message? */ 341 if (hscode == 2) { 342 hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2); 343 /* fatal initialisation error? */ 344 if (hscode != 0) { 345 mlx_free(sc); 346 return(ENXIO); 347 } 348 } 349 } 350 if (hsmsg == 1) 351 device_printf(sc->mlx_dev, "initialisation complete.\n"); 352 353 /* |
|
319 * Allocate and connect our interrupt. 320 */ 321 rid = 0; 322 sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 323 if (sc->mlx_irq == NULL) { 324 device_printf(sc->mlx_dev, "couldn't allocate interrupt\n"); 325 mlx_free(sc); 326 return(ENXIO); 327 } 328 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO, mlx_intr, sc, &sc->mlx_intr); 329 if (error) { 330 device_printf(sc->mlx_dev, "couldn't set up interrupt\n"); 331 mlx_free(sc); 332 return(ENXIO); 333 } 334 335 /* 336 * Create DMA tag for mapping buffers into controller-addressable space. 337 */ | 354 * Allocate and connect our interrupt. 355 */ 356 rid = 0; 357 sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 358 if (sc->mlx_irq == NULL) { 359 device_printf(sc->mlx_dev, "couldn't allocate interrupt\n"); 360 mlx_free(sc); 361 return(ENXIO); 362 } 363 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO, mlx_intr, sc, &sc->mlx_intr); 364 if (error) { 365 device_printf(sc->mlx_dev, "couldn't set up interrupt\n"); 366 mlx_free(sc); 367 return(ENXIO); 368 } 369 370 /* 371 * Create DMA tag for mapping buffers into controller-addressable space. 372 */ |
338 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 339 1, 0, /* alignment, boundary */ 340 BUS_SPACE_MAXADDR, /* lowaddr */ 341 BUS_SPACE_MAXADDR, /* highaddr */ 342 NULL, NULL, /* filter, filterarg */ 343 MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */ 344 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 345 0, /* flags */ | 373 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 374 1, 0, /* alignment, boundary */ 375 BUS_SPACE_MAXADDR, /* lowaddr */ 376 BUS_SPACE_MAXADDR, /* highaddr */ 377 NULL, NULL, /* filter, filterarg */ 378 MAXBSIZE, sc->mlx_sg_nseg, /* maxsize, nsegments */ 379 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 380 0, /* flags */ |
346 &sc->mlx_buffer_dmat); 347 if (error != 0) { 348 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n"); 349 return(ENOMEM); 350 } 351 352 /* 353 * Create an initial set of s/g mappings. --- 11 unchanged lines hidden (view full) --- 365 return(ENXIO); 366 } 367 368 /* 369 * We don't (yet) know where the event log is up to. 370 */ 371 sc->mlx_lastevent = -1; 372 | 381 &sc->mlx_buffer_dmat); 382 if (error != 0) { 383 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n"); 384 return(ENOMEM); 385 } 386 387 /* 388 * Create an initial set of s/g mappings. --- 11 unchanged lines hidden (view full) --- 400 return(ENXIO); 401 } 402 403 /* 404 * We don't (yet) know where the event log is up to. 405 */ 406 sc->mlx_lastevent = -1; 407 |
373 /* print a little information about the controller */ 374 mlx_describe_controller(sc); 375 | |
376 /* 377 * Do quirk/feature related things. 378 */ 379 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff; 380 switch(sc->mlx_iftype) { | 408 /* 409 * Do quirk/feature related things. 410 */ 411 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff; 412 switch(sc->mlx_iftype) { |
413 case MLX_IFTYPE_2: 414 /* These controllers don't report the firmware version in the ENQUIRY2 response */ 415 if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) { 416 device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n"); 417 return(ENXIO); 418 } 419 sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor; 420 free(meo, M_DEVBUF); 421 422 /* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */ 423 if (meo->me_fwminor < 42) { 424 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 425 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n"); 426 } 427 break; |
|
381 case MLX_IFTYPE_3: 382 /* XXX certify 3.52? */ 383 if (fwminor < 51) { 384 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 385 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n"); 386 } 387 break; 388 case MLX_IFTYPE_4: --- 27 unchanged lines hidden (view full) --- 416 417 /* 418 * No rebuild or check is in progress. 419 */ 420 sc->mlx_rebuild = -1; 421 sc->mlx_check = -1; 422 423 /* | 428 case MLX_IFTYPE_3: 429 /* XXX certify 3.52? */ 430 if (fwminor < 51) { 431 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 432 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n"); 433 } 434 break; 435 case MLX_IFTYPE_4: --- 27 unchanged lines hidden (view full) --- 463 464 /* 465 * No rebuild or check is in progress. 466 */ 467 sc->mlx_rebuild = -1; 468 sc->mlx_check = -1; 469 470 /* |
424 * Register the control device on first attach. | 471 * Create the control device. |
425 */ | 472 */ |
426 if (cdev_registered++ == 0) 427 cdevsw_add(&mlx_cdevsw); | 473 sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR, 474 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev)); |
428 429 /* 430 * Start the timeout routine. 431 */ 432 sc->mlx_timeout = timeout(mlx_periodic, sc, hz); 433 | 475 476 /* 477 * Start the timeout routine. 478 */ 479 sc->mlx_timeout = timeout(mlx_periodic, sc, hz); 480 |
481 /* print a little information about the controller */ 482 mlx_describe_controller(sc); 483 |
|
434 return(0); 435} 436 437/******************************************************************************** 438 * Locate disk resources and attach children to them. 439 */ 440void 441mlx_startup(struct mlx_softc *sc) 442{ 443 struct mlx_enq_sys_drive *mes; 444 struct mlx_sysdrive *dr; 445 int i, error; 446 | 484 return(0); 485} 486 487/******************************************************************************** 488 * Locate disk resources and attach children to them. 489 */ 490void 491mlx_startup(struct mlx_softc *sc) 492{ 493 struct mlx_enq_sys_drive *mes; 494 struct mlx_sysdrive *dr; 495 int i, error; 496 |
447 debug("called"); | 497 debug_called(1); |
448 449 /* 450 * Scan all the system drives and attach children for those that 451 * don't currently have them. 452 */ 453 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL); 454 if (mes == NULL) { 455 device_printf(sc->mlx_dev, "error fetching drive status\n"); --- 43 unchanged lines hidden (view full) --- 499 */ 500int 501mlx_detach(device_t dev) 502{ 503 struct mlx_softc *sc = device_get_softc(dev); 504 struct mlxd_softc *mlxd; 505 int i, s, error; 506 | 498 499 /* 500 * Scan all the system drives and attach children for those that 501 * don't currently have them. 502 */ 503 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL); 504 if (mes == NULL) { 505 device_printf(sc->mlx_dev, "error fetching drive status\n"); --- 43 unchanged lines hidden (view full) --- 549 */ 550int 551mlx_detach(device_t dev) 552{ 553 struct mlx_softc *sc = device_get_softc(dev); 554 struct mlxd_softc *mlxd; 555 int i, s, error; 556 |
507 debug("called"); | 557 debug_called(1); |
508 509 error = EBUSY; 510 s = splbio(); 511 if (sc->mlx_state & MLX_STATE_OPEN) 512 goto out; 513 514 for (i = 0; i < MLX_MAXDRIVES; i++) { 515 if (sc->mlx_sysdrive[i].ms_disk != 0) { --- 4 unchanged lines hidden (view full) --- 520 } 521 } 522 } 523 if ((error = mlx_shutdown(dev))) 524 goto out; 525 526 mlx_free(sc); 527 | 558 559 error = EBUSY; 560 s = splbio(); 561 if (sc->mlx_state & MLX_STATE_OPEN) 562 goto out; 563 564 for (i = 0; i < MLX_MAXDRIVES; i++) { 565 if (sc->mlx_sysdrive[i].ms_disk != 0) { --- 4 unchanged lines hidden (view full) --- 570 } 571 } 572 } 573 if ((error = mlx_shutdown(dev))) 574 goto out; 575 576 mlx_free(sc); 577 |
528 /* 529 * Deregister the control device on last detach. 530 */ 531 if (--cdev_registered == 0) 532 cdevsw_remove(&mlx_cdevsw); | |
533 error = 0; 534 out: 535 splx(s); 536 return(error); 537} 538 539/******************************************************************************** 540 * Bring the controller down to a dormant state and detach all child devices. --- 6 unchanged lines hidden (view full) --- 547 * allow shutdown if any device is open. 548 */ 549int 550mlx_shutdown(device_t dev) 551{ 552 struct mlx_softc *sc = device_get_softc(dev); 553 int i, s, error; 554 | 578 error = 0; 579 out: 580 splx(s); 581 return(error); 582} 583 584/******************************************************************************** 585 * Bring the controller down to a dormant state and detach all child devices. --- 6 unchanged lines hidden (view full) --- 592 * allow shutdown if any device is open. 593 */ 594int 595mlx_shutdown(device_t dev) 596{ 597 struct mlx_softc *sc = device_get_softc(dev); 598 int i, s, error; 599 |
555 debug("called"); | 600 debug_called(1); |
556 557 s = splbio(); 558 error = 0; 559 560 sc->mlx_state |= MLX_STATE_SHUTDOWN; 561 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 562 563 /* flush controller */ --- 22 unchanged lines hidden (view full) --- 586 * Bring the controller to a quiescent state, ready for system suspend. 587 */ 588int 589mlx_suspend(device_t dev) 590{ 591 struct mlx_softc *sc = device_get_softc(dev); 592 int s; 593 | 601 602 s = splbio(); 603 error = 0; 604 605 sc->mlx_state |= MLX_STATE_SHUTDOWN; 606 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 607 608 /* flush controller */ --- 22 unchanged lines hidden (view full) --- 631 * Bring the controller to a quiescent state, ready for system suspend. 632 */ 633int 634mlx_suspend(device_t dev) 635{ 636 struct mlx_softc *sc = device_get_softc(dev); 637 int s; 638 |
594 debug("called"); | 639 debug_called(1); |
595 596 s = splbio(); 597 sc->mlx_state |= MLX_STATE_SUSPEND; 598 599 /* flush controller */ 600 device_printf(sc->mlx_dev, "flushing cache..."); 601 printf("%s\n", mlx_flush(sc) ? "failed" : "done"); 602 --- 6 unchanged lines hidden (view full) --- 609/******************************************************************************** 610 * Bring the controller back to a state ready for operation. 611 */ 612int 613mlx_resume(device_t dev) 614{ 615 struct mlx_softc *sc = device_get_softc(dev); 616 | 640 641 s = splbio(); 642 sc->mlx_state |= MLX_STATE_SUSPEND; 643 644 /* flush controller */ 645 device_printf(sc->mlx_dev, "flushing cache..."); 646 printf("%s\n", mlx_flush(sc) ? "failed" : "done"); 647 --- 6 unchanged lines hidden (view full) --- 654/******************************************************************************** 655 * Bring the controller back to a state ready for operation. 656 */ 657int 658mlx_resume(device_t dev) 659{ 660 struct mlx_softc *sc = device_get_softc(dev); 661 |
617 debug("called"); | 662 debug_called(1); |
618 619 sc->mlx_state &= ~MLX_STATE_SUSPEND; 620 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); 621 622 return(0); 623} 624 625/******************************************************************************* 626 * Take an interrupt, or be poked by other code to look for interrupt-worthy 627 * status. 628 */ 629void 630mlx_intr(void *arg) 631{ 632 struct mlx_softc *sc = (struct mlx_softc *)arg; 633 | 663 664 sc->mlx_state &= ~MLX_STATE_SUSPEND; 665 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); 666 667 return(0); 668} 669 670/******************************************************************************* 671 * Take an interrupt, or be poked by other code to look for interrupt-worthy 672 * status. 673 */ 674void 675mlx_intr(void *arg) 676{ 677 struct mlx_softc *sc = (struct mlx_softc *)arg; 678 |
634 debug("called"); | 679 debug_called(1); |
635 636 /* collect finished commands, queue anything waiting */ 637 mlx_done(sc); 638}; 639 640/******************************************************************************* 641 * Receive a buf structure from a child device and queue it on a particular 642 * disk resource, then poke the disk resource to start as much work as it can. 643 */ 644int 645mlx_submit_buf(struct mlx_softc *sc, struct buf *bp) 646{ 647 int s; 648 | 680 681 /* collect finished commands, queue anything waiting */ 682 mlx_done(sc); 683}; 684 685/******************************************************************************* 686 * Receive a buf structure from a child device and queue it on a particular 687 * disk resource, then poke the disk resource to start as much work as it can. 688 */ 689int 690mlx_submit_buf(struct mlx_softc *sc, struct buf *bp) 691{ 692 int s; 693 |
649 debug("called"); | 694 debug_called(1); |
650 651 s = splbio(); 652 bufq_insert_tail(&sc->mlx_bufq, bp); 653 sc->mlx_waitbufs++; 654 splx(s); 655 mlx_startio(sc); 656 return(0); 657} --- 244 unchanged lines hidden (view full) --- 902/******************************************************************************** 903 * Fire off commands to periodically check the status of connected drives. 904 */ 905static void 906mlx_periodic(void *data) 907{ 908 struct mlx_softc *sc = (struct mlx_softc *)data; 909 | 695 696 s = splbio(); 697 bufq_insert_tail(&sc->mlx_bufq, bp); 698 sc->mlx_waitbufs++; 699 splx(s); 700 mlx_startio(sc); 701 return(0); 702} --- 244 unchanged lines hidden (view full) --- 947/******************************************************************************** 948 * Fire off commands to periodically check the status of connected drives. 949 */ 950static void 951mlx_periodic(void *data) 952{ 953 struct mlx_softc *sc = (struct mlx_softc *)data; 954 |
910 debug("called"); | 955 debug_called(1); |
911 912 /* 913 * Run a bus pause? 914 */ 915 if ((sc->mlx_pause.mp_which != 0) && 916 (sc->mlx_pause.mp_when > 0) && 917 (time_second >= sc->mlx_pause.mp_when)){ 918 --- 22 unchanged lines hidden (view full) --- 941 } else if (time_second > (sc->mlx_lastpoll + 10)) { 942 sc->mlx_lastpoll = time_second; 943 944 /* 945 * Check controller status. 946 * 947 * XXX Note that this may not actually launch a command in situations of high load. 948 */ | 956 957 /* 958 * Run a bus pause? 959 */ 960 if ((sc->mlx_pause.mp_which != 0) && 961 (sc->mlx_pause.mp_when > 0) && 962 (time_second >= sc->mlx_pause.mp_when)){ 963 --- 22 unchanged lines hidden (view full) --- 986 } else if (time_second > (sc->mlx_lastpoll + 10)) { 987 sc->mlx_lastpoll = time_second; 988 989 /* 990 * Check controller status. 991 * 992 * XXX Note that this may not actually launch a command in situations of high load. 993 */ |
949 mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(struct mlx_enquiry), mlx_periodic_enquiry); | 994 mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY, 995 imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry); |
950 951 /* 952 * Check system drive status. 953 * 954 * XXX This might be better left to event-driven detection, eg. I/O to an offline 955 * drive will detect it's offline, rebuilds etc. should detect the drive is back 956 * online. 957 */ --- 17 unchanged lines hidden (view full) --- 975/******************************************************************************** 976 * Handle the result of an ENQUIRY command instigated by periodic status polling. 977 */ 978static void 979mlx_periodic_enquiry(struct mlx_command *mc) 980{ 981 struct mlx_softc *sc = mc->mc_sc; 982 | 996 997 /* 998 * Check system drive status. 999 * 1000 * XXX This might be better left to event-driven detection, eg. I/O to an offline 1001 * drive will detect it's offline, rebuilds etc. should detect the drive is back 1002 * online. 1003 */ --- 17 unchanged lines hidden (view full) --- 1021/******************************************************************************** 1022 * Handle the result of an ENQUIRY command instigated by periodic status polling. 1023 */ 1024static void 1025mlx_periodic_enquiry(struct mlx_command *mc) 1026{ 1027 struct mlx_softc *sc = mc->mc_sc; 1028 |
983 debug("called"); | 1029 debug_called(1); |
984 985 /* Command completed OK? */ 986 if (mc->mc_status != 0) { | 1030 1031 /* Command completed OK? */ 1032 if (mc->mc_status != 0) { |
987 device_printf(sc->mlx_dev, "periodic enquiry failed\n"); | 1033 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc)); |
988 goto out; 989 } 990 991 /* respond to command */ 992 switch(mc->mc_mailbox[0]) { 993 /* | 1034 goto out; 1035 } 1036 1037 /* respond to command */ 1038 switch(mc->mc_mailbox[0]) { 1039 /* |
1040 * This is currently a bit fruitless, as we don't know how to extract the eventlog 1041 * pointer yet. 1042 */ 1043 case MLX_CMD_ENQUIRY_OLD: 1044 { 1045 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data; 1046 struct mlx_enquiry_old *meo = (struct mlx_enquiry_old *)mc->mc_data; 1047 int i; 1048 1049 /* convert data in-place to new format */ 1050 for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) { 1051 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan; 1052 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ; 1053 } 1054 me->me_misc_flags = 0; 1055 me->me_rebuild_count = meo->me_rebuild_count; 1056 me->me_dead_count = meo->me_dead_count; 1057 me->me_critical_sd_count = meo->me_critical_sd_count; 1058 me->me_event_log_seq_num = 0; 1059 me->me_offline_sd_count = meo->me_offline_sd_count; 1060 me->me_max_commands = meo->me_max_commands; 1061 me->me_rebuild_flag = meo->me_rebuild_flag; 1062 me->me_fwmajor = meo->me_fwmajor; 1063 me->me_fwminor = meo->me_fwminor; 1064 me->me_status_flags = meo->me_status_flags; 1065 me->me_flash_age = meo->me_flash_age; 1066 for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) { 1067 if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) { 1068 me->me_drvsize[i] = 0; /* drive beyond supported range */ 1069 } else { 1070 me->me_drvsize[i] = meo->me_drvsize[i]; 1071 } 1072 } 1073 me->me_num_sys_drvs = meo->me_num_sys_drvs; 1074 } 1075 /* FALLTHROUGH */ 1076 1077 /* |
|
994 * Generic controller status update. We could do more with this than just 995 * checking the event log. 996 */ 997 case MLX_CMD_ENQUIRY: 998 { 999 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data; 1000 1001 if (sc->mlx_lastevent == -1) { 1002 /* initialise our view of the event log */ 1003 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num; 1004 } else if (me->me_event_log_seq_num != sc->mlx_lastevent) { 1005 /* record where current events are up to */ 1006 sc->mlx_currevent = me->me_event_log_seq_num; | 1078 * Generic controller status update. We could do more with this than just 1079 * checking the event log. 1080 */ 1081 case MLX_CMD_ENQUIRY: 1082 { 1083 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data; 1084 1085 if (sc->mlx_lastevent == -1) { 1086 /* initialise our view of the event log */ 1087 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num; 1088 } else if (me->me_event_log_seq_num != sc->mlx_lastevent) { 1089 /* record where current events are up to */ 1090 sc->mlx_currevent = me->me_event_log_seq_num; |
1007 device_printf(sc->mlx_dev, "event log pointer was %d, now %d\n", 1008 sc->mlx_lastevent, sc->mlx_currevent); | 1091 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent); |
1009 1010 /* drain new eventlog entries */ 1011 mlx_periodic_eventlog_poll(sc); 1012 } 1013 break; 1014 } 1015 case MLX_CMD_ENQSYSDRIVE: 1016 { --- 43 unchanged lines hidden (view full) --- 1060 */ 1061static void 1062mlx_periodic_eventlog_poll(struct mlx_softc *sc) 1063{ 1064 struct mlx_command *mc; 1065 void *result = NULL; 1066 int error; 1067 | 1092 1093 /* drain new eventlog entries */ 1094 mlx_periodic_eventlog_poll(sc); 1095 } 1096 break; 1097 } 1098 case MLX_CMD_ENQSYSDRIVE: 1099 { --- 43 unchanged lines hidden (view full) --- 1143 */ 1144static void 1145mlx_periodic_eventlog_poll(struct mlx_softc *sc) 1146{ 1147 struct mlx_command *mc; 1148 void *result = NULL; 1149 int error; 1150 |
1068 debug("called"); | 1151 debug_called(1); |
1069 1070 /* get ourselves a command buffer */ 1071 error = 1; 1072 if ((mc = mlx_alloccmd(sc)) == NULL) 1073 goto out; 1074 /* allocate the response structure */ 1075 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL) 1076 goto out; --- 47 unchanged lines hidden (view full) --- 1124 1125static void 1126mlx_periodic_eventlog_respond(struct mlx_command *mc) 1127{ 1128 struct mlx_softc *sc = mc->mc_sc; 1129 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data; 1130 char *reason; 1131 | 1152 1153 /* get ourselves a command buffer */ 1154 error = 1; 1155 if ((mc = mlx_alloccmd(sc)) == NULL) 1156 goto out; 1157 /* allocate the response structure */ 1158 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL) 1159 goto out; --- 47 unchanged lines hidden (view full) --- 1207 1208static void 1209mlx_periodic_eventlog_respond(struct mlx_command *mc) 1210{ 1211 struct mlx_softc *sc = mc->mc_sc; 1212 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data; 1213 char *reason; 1214 |
1132 debug("called"); | 1215 debug_called(1); |
1133 1134 sc->mlx_lastevent++; /* next message... */ 1135 if (mc->mc_status == 0) { 1136 1137 /* handle event log message */ 1138 switch(el->el_type) { 1139 /* 1140 * This is the only sort of message we understand at the moment. --- 175 unchanged lines hidden (view full) --- 1316 */ 1317static void * 1318mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc)) 1319{ 1320 struct mlx_command *mc; 1321 void *result; 1322 int error; 1323 | 1216 1217 sc->mlx_lastevent++; /* next message... */ 1218 if (mc->mc_status == 0) { 1219 1220 /* handle event log message */ 1221 switch(el->el_type) { 1222 /* 1223 * This is the only sort of message we understand at the moment. --- 175 unchanged lines hidden (view full) --- 1399 */ 1400static void * 1401mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc)) 1402{ 1403 struct mlx_command *mc; 1404 void *result; 1405 int error; 1406 |
1324 debug("called"); | 1407 debug_called(1); |
1325 1326 /* get ourselves a command buffer */ 1327 error = 1; 1328 result = NULL; 1329 if ((mc = mlx_alloccmd(sc)) == NULL) 1330 goto out; 1331 /* allocate the response structure */ 1332 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL) --- 49 unchanged lines hidden (view full) --- 1382 * the flush operation completes or fails. 1383 */ 1384static int 1385mlx_flush(struct mlx_softc *sc) 1386{ 1387 struct mlx_command *mc; 1388 int error; 1389 | 1408 1409 /* get ourselves a command buffer */ 1410 error = 1; 1411 result = NULL; 1412 if ((mc = mlx_alloccmd(sc)) == NULL) 1413 goto out; 1414 /* allocate the response structure */ 1415 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL) --- 49 unchanged lines hidden (view full) --- 1465 * the flush operation completes or fails. 1466 */ 1467static int 1468mlx_flush(struct mlx_softc *sc) 1469{ 1470 struct mlx_command *mc; 1471 int error; 1472 |
1390 debug("called"); | 1473 debug_called(1); |
1391 1392 /* get ourselves a command buffer */ 1393 error = 1; 1394 if ((mc = mlx_alloccmd(sc)) == NULL) 1395 goto out; 1396 /* get a command slot */ 1397 if (mlx_getslot(mc)) 1398 goto out; --- 25 unchanged lines hidden (view full) --- 1424 * operation has started or been refused. 1425 */ 1426static int 1427mlx_rebuild(struct mlx_softc *sc, int channel, int target) 1428{ 1429 struct mlx_command *mc; 1430 int error; 1431 | 1474 1475 /* get ourselves a command buffer */ 1476 error = 1; 1477 if ((mc = mlx_alloccmd(sc)) == NULL) 1478 goto out; 1479 /* get a command slot */ 1480 if (mlx_getslot(mc)) 1481 goto out; --- 25 unchanged lines hidden (view full) --- 1507 * operation has started or been refused. 1508 */ 1509static int 1510mlx_rebuild(struct mlx_softc *sc, int channel, int target) 1511{ 1512 struct mlx_command *mc; 1513 int error; 1514 |
1432 debug("called"); | 1515 debug_called(1); |
1433 1434 /* get ourselves a command buffer */ 1435 error = 0x10000; 1436 if ((mc = mlx_alloccmd(sc)) == NULL) 1437 goto out; 1438 /* get a command slot */ 1439 if (mlx_getslot(mc)) 1440 goto out; --- 25 unchanged lines hidden (view full) --- 1466 * Interrupts need to be enabled; returns nonzero on error. 1467 */ 1468static int 1469mlx_wait_command(struct mlx_command *mc) 1470{ 1471 struct mlx_softc *sc = mc->mc_sc; 1472 int error, count; 1473 | 1516 1517 /* get ourselves a command buffer */ 1518 error = 0x10000; 1519 if ((mc = mlx_alloccmd(sc)) == NULL) 1520 goto out; 1521 /* get a command slot */ 1522 if (mlx_getslot(mc)) 1523 goto out; --- 25 unchanged lines hidden (view full) --- 1549 * Interrupts need to be enabled; returns nonzero on error. 1550 */ 1551static int 1552mlx_wait_command(struct mlx_command *mc) 1553{ 1554 struct mlx_softc *sc = mc->mc_sc; 1555 int error, count; 1556 |
1474 debug("called"); | 1557 debug_called(1); |
1475 1476 mc->mc_complete = NULL; 1477 mc->mc_private = mc; /* wake us when you're done */ 1478 if ((error = mlx_start(mc)) != 0) 1479 return(error); 1480 1481 count = 0; 1482 /* XXX better timeout? */ 1483 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) { 1484 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz); 1485 } 1486 1487 if (mc->mc_status != 0) { | 1558 1559 mc->mc_complete = NULL; 1560 mc->mc_private = mc; /* wake us when you're done */ 1561 if ((error = mlx_start(mc)) != 0) 1562 return(error); 1563 1564 count = 0; 1565 /* XXX better timeout? */ 1566 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) { 1567 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz); 1568 } 1569 1570 if (mc->mc_status != 0) { |
1488 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status); | 1571 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); |
1489 return(EIO); 1490 } 1491 return(0); 1492} 1493 1494 1495/******************************************************************************** 1496 * Start the command (mc) and busy-wait for it to complete. 1497 * | 1572 return(EIO); 1573 } 1574 return(0); 1575} 1576 1577 1578/******************************************************************************** 1579 * Start the command (mc) and busy-wait for it to complete. 1580 * |
1498 * Should only be used when interrupts are not available. Returns 0 on | 1581 * Should only be used when interrupts can't be relied upon. Returns 0 on |
1499 * success, nonzero on error. 1500 * Successfully completed commands are dequeued. 1501 */ 1502static int 1503mlx_poll_command(struct mlx_command *mc) 1504{ 1505 struct mlx_softc *sc = mc->mc_sc; 1506 int error, count, s; 1507 | 1582 * success, nonzero on error. 1583 * Successfully completed commands are dequeued. 1584 */ 1585static int 1586mlx_poll_command(struct mlx_command *mc) 1587{ 1588 struct mlx_softc *sc = mc->mc_sc; 1589 int error, count, s; 1590 |
1508 debug("called"); | 1591 debug_called(1); |
1509 1510 mc->mc_complete = NULL; 1511 mc->mc_private = NULL; /* we will poll for it */ 1512 if ((error = mlx_start(mc)) != 0) 1513 return(error); 1514 1515 count = 0; 1516 do { 1517 /* poll for completion */ 1518 mlx_done(mc->mc_sc); | 1592 1593 mc->mc_complete = NULL; 1594 mc->mc_private = NULL; /* we will poll for it */ 1595 if ((error = mlx_start(mc)) != 0) 1596 return(error); 1597 1598 count = 0; 1599 do { 1600 /* poll for completion */ 1601 mlx_done(mc->mc_sc); |
1519 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000)); | 1602 1603 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000)); |
1520 if (mc->mc_status != MLX_STATUS_BUSY) { 1521 s = splbio(); 1522 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); 1523 splx(s); 1524 return(0); 1525 } 1526 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status); 1527 return(EIO); 1528} 1529 1530/******************************************************************************** 1531 * Pull as much work off the softc's work queue as possible and give it to the 1532 * controller. Leave a couple of slots free for emergencies. 1533 * 1534 * Must be called at splbio or in an equivalent fashion that prevents | 1604 if (mc->mc_status != MLX_STATUS_BUSY) { 1605 s = splbio(); 1606 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); 1607 splx(s); 1608 return(0); 1609 } 1610 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status); 1611 return(EIO); 1612} 1613 1614/******************************************************************************** 1615 * Pull as much work off the softc's work queue as possible and give it to the 1616 * controller. Leave a couple of slots free for emergencies. 1617 * 1618 * Must be called at splbio or in an equivalent fashion that prevents |
1535 * reentry or activity on the bufq.. | 1619 * reentry or activity on the bufq. |
1536 */ 1537static void 1538mlx_startio(struct mlx_softc *sc) 1539{ 1540 struct mlx_command *mc; 1541 struct mlxd_softc *mlxd; 1542 struct buf *bp; 1543 int blkcount; --- 27 unchanged lines hidden (view full) --- 1571 1572 /* connect the buf to the command */ 1573 mc->mc_complete = mlx_completeio; 1574 mc->mc_private = bp; 1575 mc->mc_data = bp->b_data; 1576 mc->mc_length = bp->b_bcount; 1577 if (bp->b_flags & B_READ) { 1578 mc->mc_flags |= MLX_CMD_DATAIN; | 1620 */ 1621static void 1622mlx_startio(struct mlx_softc *sc) 1623{ 1624 struct mlx_command *mc; 1625 struct mlxd_softc *mlxd; 1626 struct buf *bp; 1627 int blkcount; --- 27 unchanged lines hidden (view full) --- 1655 1656 /* connect the buf to the command */ 1657 mc->mc_complete = mlx_completeio; 1658 mc->mc_private = bp; 1659 mc->mc_data = bp->b_data; 1660 mc->mc_length = bp->b_bcount; 1661 if (bp->b_flags & B_READ) { 1662 mc->mc_flags |= MLX_CMD_DATAIN; |
1579 cmd = MLX_CMD_READOLDSG; | 1663 cmd = MLX_CMD_READSG; |
1580 } else { 1581 mc->mc_flags |= MLX_CMD_DATAOUT; | 1664 } else { 1665 mc->mc_flags |= MLX_CMD_DATAOUT; |
1582 cmd = MLX_CMD_WRITEOLDSG; | 1666 cmd = MLX_CMD_WRITESG; |
1583 } 1584 1585 /* map the command so the controller can work with it */ 1586 mlx_mapcmd(mc); 1587 1588 /* build a suitable I/O command (assumes 512-byte rounded transfers) */ 1589 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1; 1590 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive; 1591 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE; 1592 1593 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size) 1594 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n", 1595 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size); 1596 1597 /* 1598 * Build the I/O command. Note that the SG list type bits are set to zero, 1599 * denoting the format of SG list that we are using. 1600 */ | 1667 } 1668 1669 /* map the command so the controller can work with it */ 1670 mlx_mapcmd(mc); 1671 1672 /* build a suitable I/O command (assumes 512-byte rounded transfers) */ 1673 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1; 1674 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive; 1675 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE; 1676 1677 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size) 1678 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n", 1679 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size); 1680 1681 /* 1682 * Build the I/O command. Note that the SG list type bits are set to zero, 1683 * denoting the format of SG list that we are using. 1684 */ |
1601 mlx_make_type5(mc, cmd, 1602 blkcount & 0xff, /* xfer length low byte */ 1603 (driveno << 3) | ((blkcount >> 8) & 0x07), /* target and length high 3 bits */ 1604 bp->b_pblkno, /* physical block number */ 1605 mc->mc_sgphys, /* location of SG list */ 1606 mc->mc_nsgent & 0x3f); /* size of SG list (top 2 bits clear) */ | 1685 if (sc->mlx_iftype == MLX_IFTYPE_2) { 1686 mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD, 1687 blkcount & 0xff, /* xfer length low byte */ 1688 bp->b_pblkno, /* physical block number */ 1689 driveno, /* target drive number */ 1690 mc->mc_sgphys, /* location of SG list */ 1691 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */ 1692 } else { 1693 mlx_make_type5(mc, cmd, 1694 blkcount & 0xff, /* xfer length low byte */ 1695 (driveno << 3) | ((blkcount >> 8) & 0x07), /* target and length high 3 bits */ 1696 bp->b_pblkno, /* physical block number */ 1697 mc->mc_sgphys, /* location of SG list */ 1698 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */ 1699 } |
1607 | 1700 |
1608 | |
1609 /* try to give command to controller */ 1610 if (mlx_start(mc) != 0) { 1611 /* fail the command */ 1612 mc->mc_status = MLX_STATUS_WEDGED; 1613 mlx_completeio(mc); 1614 } 1615 s = splbio(); 1616 } --- 33 unchanged lines hidden (view full) --- 1650 } 1651 } 1652 mlx_releasecmd(mc); 1653 mlxd_intr(bp); 1654} 1655 1656/******************************************************************************** 1657 * Take a command from user-space and try to run it. | 1701 /* try to give command to controller */ 1702 if (mlx_start(mc) != 0) { 1703 /* fail the command */ 1704 mc->mc_status = MLX_STATUS_WEDGED; 1705 mlx_completeio(mc); 1706 } 1707 s = splbio(); 1708 } --- 33 unchanged lines hidden (view full) --- 1742 } 1743 } 1744 mlx_releasecmd(mc); 1745 mlxd_intr(bp); 1746} 1747 1748/******************************************************************************** 1749 * Take a command from user-space and try to run it. |
1750 * 1751 * XXX Note that this can't perform very much in the way of error checking, and 1752 * as such, applications _must_ be considered trustworthy. 1753 * XXX Commands using S/G for data are not supported. |
|
1658 */ 1659static int 1660mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu) 1661{ 1662 struct mlx_command *mc; | 1754 */ 1755static int 1756mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu) 1757{ 1758 struct mlx_command *mc; |
1759 struct mlx_dcdb *dcdb; |
|
1663 void *kbuf; 1664 int error; 1665 | 1760 void *kbuf; 1761 int error; 1762 |
1763 debug_called(0); 1764 |
|
1666 kbuf = NULL; 1667 mc = NULL; | 1765 kbuf = NULL; 1766 mc = NULL; |
1767 dcdb = NULL; |
|
1668 error = ENOMEM; | 1768 error = ENOMEM; |
1669 /* get a kernel buffer for the transfer */ 1670 if (mu->mu_datasize > 0) { 1671 if ((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) 1672 goto out; 1673 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) < sizeof(u_int32_t)))) { 1674 error = EINVAL; 1675 goto out; 1676 } 1677 } 1678 /* get ourselves a command buffer */ | 1769 1770 /* get ourselves a command and copy in from user space */ |
1679 if ((mc = mlx_alloccmd(sc)) == NULL) 1680 goto out; | 1771 if ((mc = mlx_alloccmd(sc)) == NULL) 1772 goto out; |
1681 1682 /* copy the command and data */ | |
1683 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox)); | 1773 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox)); |
1684 if ((mu->mu_datasize > 0) && ((error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))) 1685 goto out; | 1774 debug(0, "got command buffer"); |
1686 | 1775 |
1776 /* if we need a buffer for data transfer, allocate one and copy in its initial contents */ 1777 if (mu->mu_datasize > 0) { 1778 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) || 1779 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) 1780 goto out; 1781 debug(0, "got kernel buffer"); 1782 } 1783 |
|
1687 /* get a command slot */ 1688 if (mlx_getslot(mc)) 1689 goto out; | 1784 /* get a command slot */ 1785 if (mlx_getslot(mc)) 1786 goto out; |
1690 | 1787 debug(0, "got a slot"); 1788 |
1691 /* map the command so the controller can see it */ 1692 mc->mc_data = kbuf; 1693 mc->mc_length = mu->mu_datasize; 1694 mlx_mapcmd(mc); | 1789 /* map the command so the controller can see it */ 1790 mc->mc_data = kbuf; 1791 mc->mc_length = mu->mu_datasize; 1792 mlx_mapcmd(mc); |
1793 debug(0, "mapped"); |
|
1695 | 1794 |
1696 /* if there's a data buffer, fix up the command */ | 1795 /* 1796 * If this is a passthrough SCSI command, the DCDB is packed at the 1797 * beginning of the data area. Fix up the DCDB to point to the correct physical 1798 * address and override any bufptr supplied by the caller since we know 1799 * what it's meant to be. 1800 */ 1801 if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) { 1802 dcdb = (struct mlx_dcdb *)kbuf; 1803 dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb); 1804 mu->mu_bufptr = 8; 1805 } 1806 1807 /* 1808 * If there's a data buffer, fix up the command's buffer pointer. 1809 */ |
1697 if (mu->mu_datasize > 0) { | 1810 if (mu->mu_datasize > 0) { |
1698 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_length & 0xff; 1699 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_length >> 8) & 0xff; 1700 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_length >> 16) & 0xff; 1701 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_length >> 24) & 0xff; | 1811 1812 /* range check the pointer to physical buffer address */ 1813 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) { 1814 error = EINVAL; 1815 goto out; 1816 } 1817 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_dataphys & 0xff; 1818 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8) & 0xff; 1819 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff; 1820 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff; |
1702 } | 1821 } |
1822 debug(0, "command fixup"); |
|
1703 1704 /* submit the command and wait */ 1705 if ((error = mlx_wait_command(mc)) != 0) 1706 goto out; 1707 1708 /* copy out status and data */ 1709 mu->mu_status = mc->mc_status; 1710 if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize)))) --- 20 unchanged lines hidden (view full) --- 1731 * 4 slots free for priority commands. 1732 */ 1733static int 1734mlx_getslot(struct mlx_command *mc) 1735{ 1736 struct mlx_softc *sc = mc->mc_sc; 1737 int s, slot; 1738 | 1823 1824 /* submit the command and wait */ 1825 if ((error = mlx_wait_command(mc)) != 0) 1826 goto out; 1827 1828 /* copy out status and data */ 1829 mu->mu_status = mc->mc_status; 1830 if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize)))) --- 20 unchanged lines hidden (view full) --- 1851 * 4 slots free for priority commands. 1852 */ 1853static int 1854mlx_getslot(struct mlx_command *mc) 1855{ 1856 struct mlx_softc *sc = mc->mc_sc; 1857 int s, slot; 1858 |
1739 debug("called mc %p sc %p", mc, sc); | 1859 debug_called(1); |
1740 1741 /* enforce slot-usage limit */ 1742 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? 1743 sc->mlx_maxiop : sc->mlx_maxiop - 4)) 1744 return(EBUSY); 1745 1746 /* 1747 * Allocate an outstanding command slot 1748 * 1749 * XXX linear search is slow 1750 */ 1751 s = splbio(); 1752 for (slot = 0; slot < sc->mlx_maxiop; slot++) { | 1860 1861 /* enforce slot-usage limit */ 1862 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? 1863 sc->mlx_maxiop : sc->mlx_maxiop - 4)) 1864 return(EBUSY); 1865 1866 /* 1867 * Allocate an outstanding command slot 1868 * 1869 * XXX linear search is slow 1870 */ 1871 s = splbio(); 1872 for (slot = 0; slot < sc->mlx_maxiop; slot++) { |
1753 debug("try slot %d", slot); | 1873 debug(2, "try slot %d", slot); |
1754 if (sc->mlx_busycmd[slot] == NULL) 1755 break; 1756 } 1757 if (slot < sc->mlx_maxiop) { 1758 sc->mlx_busycmd[slot] = mc; 1759 sc->mlx_busycmds++; 1760 } 1761 splx(s); 1762 1763 /* out of slots? */ 1764 if (slot >= sc->mlx_maxiop) 1765 return(EBUSY); 1766 | 1874 if (sc->mlx_busycmd[slot] == NULL) 1875 break; 1876 } 1877 if (slot < sc->mlx_maxiop) { 1878 sc->mlx_busycmd[slot] = mc; 1879 sc->mlx_busycmds++; 1880 } 1881 splx(s); 1882 1883 /* out of slots? */ 1884 if (slot >= sc->mlx_maxiop) 1885 return(EBUSY); 1886 |
1767 debug("got slot %d", slot); | 1887 debug(2, "got slot %d", slot); |
1768 mc->mc_slot = slot; 1769 return(0); 1770} 1771 1772/******************************************************************************** 1773 * Map/unmap (mc)'s data in the controller's addressable space. 1774 */ 1775static void 1776mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1777{ 1778 struct mlx_command *mc = (struct mlx_command *)arg; 1779 struct mlx_softc *sc = mc->mc_sc; 1780 struct mlx_sgentry *sg; 1781 int i; 1782 | 1888 mc->mc_slot = slot; 1889 return(0); 1890} 1891 1892/******************************************************************************** 1893 * Map/unmap (mc)'s data in the controller's addressable space. 1894 */ 1895static void 1896mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1897{ 1898 struct mlx_command *mc = (struct mlx_command *)arg; 1899 struct mlx_softc *sc = mc->mc_sc; 1900 struct mlx_sgentry *sg; 1901 int i; 1902 |
1783 debug("called"); | 1903 debug_called(1); |
1784 1785 /* get base address of s/g table */ | 1904 1905 /* get base address of s/g table */ |
1786 sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG); | 1906 sg = sc->mlx_sgtable + (mc->mc_slot * sc->mlx_sg_nseg); |
1787 1788 /* save s/g table information in command */ 1789 mc->mc_nsgent = nsegments; | 1907 1908 /* save s/g table information in command */ 1909 mc->mc_nsgent = nsegments; |
1790 mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry)); | 1910 mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * sc->mlx_sg_nseg * sizeof(struct mlx_sgentry)); |
1791 mc->mc_dataphys = segs[0].ds_addr; 1792 1793 /* populate s/g table */ 1794 for (i = 0; i < nsegments; i++, sg++) { 1795 sg->sg_addr = segs[i].ds_addr; 1796 sg->sg_count = segs[i].ds_len; 1797 } 1798} 1799 1800static void 1801mlx_mapcmd(struct mlx_command *mc) 1802{ 1803 struct mlx_softc *sc = mc->mc_sc; 1804 | 1911 mc->mc_dataphys = segs[0].ds_addr; 1912 1913 /* populate s/g table */ 1914 for (i = 0; i < nsegments; i++, sg++) { 1915 sg->sg_addr = segs[i].ds_addr; 1916 sg->sg_count = segs[i].ds_len; 1917 } 1918} 1919 1920static void 1921mlx_mapcmd(struct mlx_command *mc) 1922{ 1923 struct mlx_softc *sc = mc->mc_sc; 1924 |
1805 debug("called"); | 1925 debug_called(1); |
1806 1807 /* if the command involves data at all */ 1808 if (mc->mc_data != NULL) { 1809 1810 /* map the data buffer into bus space and build the s/g list */ 1811 bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length, 1812 mlx_setup_dmamap, mc, 0); 1813 if (mc->mc_flags & MLX_CMD_DATAIN) 1814 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD); 1815 if (mc->mc_flags & MLX_CMD_DATAOUT) 1816 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE); 1817 } 1818} 1819 1820static void 1821mlx_unmapcmd(struct mlx_command *mc) 1822{ 1823 struct mlx_softc *sc = mc->mc_sc; 1824 | 1926 1927 /* if the command involves data at all */ 1928 if (mc->mc_data != NULL) { 1929 1930 /* map the data buffer into bus space and build the s/g list */ 1931 bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length, 1932 mlx_setup_dmamap, mc, 0); 1933 if (mc->mc_flags & MLX_CMD_DATAIN) 1934 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD); 1935 if (mc->mc_flags & MLX_CMD_DATAOUT) 1936 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE); 1937 } 1938} 1939 1940static void 1941mlx_unmapcmd(struct mlx_command *mc) 1942{ 1943 struct mlx_softc *sc = mc->mc_sc; 1944 |
1825 debug("called"); | 1945 debug_called(1); |
1826 1827 /* if the command involved data at all */ 1828 if (mc->mc_data != NULL) { 1829 1830 if (mc->mc_flags & MLX_CMD_DATAIN) 1831 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD); 1832 if (mc->mc_flags & MLX_CMD_DATAOUT) 1833 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE); --- 8 unchanged lines hidden (view full) --- 1842 * Can be called at any interrupt level, with or without interrupts enabled. 1843 */ 1844static int 1845mlx_start(struct mlx_command *mc) 1846{ 1847 struct mlx_softc *sc = mc->mc_sc; 1848 int i, s, done; 1849 | 1946 1947 /* if the command involved data at all */ 1948 if (mc->mc_data != NULL) { 1949 1950 if (mc->mc_flags & MLX_CMD_DATAIN) 1951 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD); 1952 if (mc->mc_flags & MLX_CMD_DATAOUT) 1953 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE); --- 8 unchanged lines hidden (view full) --- 1962 * Can be called at any interrupt level, with or without interrupts enabled. 1963 */ 1964static int 1965mlx_start(struct mlx_command *mc) 1966{ 1967 struct mlx_softc *sc = mc->mc_sc; 1968 int i, s, done; 1969 |
1850 debug("called"); | 1970 debug_called(1); |
1851 1852 /* save the slot number as ident so we can handle this command when complete */ 1853 mc->mc_mailbox[0x1] = mc->mc_slot; 1854 1855 /* mark the command as currently being processed */ 1856 mc->mc_status = MLX_STATUS_BUSY; 1857 1858 /* set a default 60-second timeout XXX tunable? XXX not currently used */ --- 35 unchanged lines hidden (view full) --- 1894static int 1895mlx_done(struct mlx_softc *sc) 1896{ 1897 struct mlx_command *mc; 1898 int s, result; 1899 u_int8_t slot; 1900 u_int16_t status; 1901 | 1971 1972 /* save the slot number as ident so we can handle this command when complete */ 1973 mc->mc_mailbox[0x1] = mc->mc_slot; 1974 1975 /* mark the command as currently being processed */ 1976 mc->mc_status = MLX_STATUS_BUSY; 1977 1978 /* set a default 60-second timeout XXX tunable? XXX not currently used */ --- 35 unchanged lines hidden (view full) --- 2014static int 2015mlx_done(struct mlx_softc *sc) 2016{ 2017 struct mlx_command *mc; 2018 int s, result; 2019 u_int8_t slot; 2020 u_int16_t status; 2021 |
1902 debug("called"); | 2022 debug_called(2); |
1903 1904 result = 0; 1905 1906 /* loop collecting completed commands */ 1907 s = splbio(); 1908 for (;;) { 1909 /* poll for a completed command's identifier and status */ 1910 if (sc->mlx_findcomplete(sc, &slot, &status)) { --- 31 unchanged lines hidden (view full) --- 1942 * Perform post-completion processing for commands on (sc). 1943 */ 1944static void 1945mlx_complete(struct mlx_softc *sc) 1946{ 1947 struct mlx_command *mc, *nc; 1948 int s, count; 1949 | 2023 2024 result = 0; 2025 2026 /* loop collecting completed commands */ 2027 s = splbio(); 2028 for (;;) { 2029 /* poll for a completed command's identifier and status */ 2030 if (sc->mlx_findcomplete(sc, &slot, &status)) { --- 31 unchanged lines hidden (view full) --- 2062 * Perform post-completion processing for commands on (sc). 2063 */ 2064static void 2065mlx_complete(struct mlx_softc *sc) 2066{ 2067 struct mlx_command *mc, *nc; 2068 int s, count; 2069 |
1950 debug("called"); | 2070 debug_called(2); |
1951 1952 /* avoid reentrancy XXX might want to signal and request a restart */ 1953 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING)) 1954 return; 1955 1956 s = splbio(); 1957 count = 0; 1958 --- 59 unchanged lines hidden (view full) --- 2018 */ 2019static struct mlx_command * 2020mlx_alloccmd(struct mlx_softc *sc) 2021{ 2022 struct mlx_command *mc; 2023 int error; 2024 int s; 2025 | 2071 2072 /* avoid reentrancy XXX might want to signal and request a restart */ 2073 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING)) 2074 return; 2075 2076 s = splbio(); 2077 count = 0; 2078 --- 59 unchanged lines hidden (view full) --- 2138 */ 2139static struct mlx_command * 2140mlx_alloccmd(struct mlx_softc *sc) 2141{ 2142 struct mlx_command *mc; 2143 int error; 2144 int s; 2145 |
2026 debug("called"); | 2146 debug_called(1); |
2027 2028 s = splbio(); 2029 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) 2030 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 2031 splx(s); 2032 2033 /* allocate a new command buffer? */ 2034 if (mc == NULL) { --- 17 unchanged lines hidden (view full) --- 2052 * XXX It might be a good idea to limit the number of commands we save for reuse 2053 * if it's shown that this list bloats out massively. 2054 */ 2055static void 2056mlx_releasecmd(struct mlx_command *mc) 2057{ 2058 int s; 2059 | 2147 2148 s = splbio(); 2149 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) 2150 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 2151 splx(s); 2152 2153 /* allocate a new command buffer? */ 2154 if (mc == NULL) { --- 17 unchanged lines hidden (view full) --- 2172 * XXX It might be a good idea to limit the number of commands we save for reuse 2173 * if it's shown that this list bloats out massively. 2174 */ 2175static void 2176mlx_releasecmd(struct mlx_command *mc) 2177{ 2178 int s; 2179 |
2060 debug("called"); | 2180 debug_called(1); |
2061 2062 s = splbio(); 2063 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link); 2064 splx(s); 2065} 2066 2067/******************************************************************************** 2068 * Permanently discard a command buffer. 2069 */ 2070static void 2071mlx_freecmd(struct mlx_command *mc) 2072{ 2073 struct mlx_softc *sc = mc->mc_sc; 2074 | 2181 2182 s = splbio(); 2183 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link); 2184 splx(s); 2185} 2186 2187/******************************************************************************** 2188 * Permanently discard a command buffer. 2189 */ 2190static void 2191mlx_freecmd(struct mlx_command *mc) 2192{ 2193 struct mlx_softc *sc = mc->mc_sc; 2194 |
2075 debug("called"); 2076 | 2195 debug_called(1); |
2077 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap); 2078 free(mc, M_DEVBUF); 2079} 2080 2081 2082/******************************************************************************** 2083 ******************************************************************************** 2084 Type 3 interface accessor methods --- 6 unchanged lines hidden (view full) --- 2091 * 2092 * Must be called at splbio or in a fashion that prevents reentry. 2093 */ 2094static int 2095mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2096{ 2097 int i; 2098 | 2196 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap); 2197 free(mc, M_DEVBUF); 2198} 2199 2200 2201/******************************************************************************** 2202 ******************************************************************************** 2203 Type 3 interface accessor methods --- 6 unchanged lines hidden (view full) --- 2210 * 2211 * Must be called at splbio or in a fashion that prevents reentry. 2212 */ 2213static int 2214mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2215{ 2216 int i; 2217 |
2099 debug("called"); | 2218 debug_called(2); |
2100 2101 /* ready for our command? */ 2102 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) { 2103 /* copy mailbox data to window */ 2104 for (i = 0; i < 13; i++) 2105 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2106 2107 /* post command */ --- 8 unchanged lines hidden (view full) --- 2116 * and recover the slot number and status code. 2117 * 2118 * Must be called at splbio or in a fashion that prevents reentry. 2119 */ 2120static int 2121mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2122{ 2123 | 2219 2220 /* ready for our command? */ 2221 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) { 2222 /* copy mailbox data to window */ 2223 for (i = 0; i < 13; i++) 2224 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2225 2226 /* post command */ --- 8 unchanged lines hidden (view full) --- 2235 * and recover the slot number and status code. 2236 * 2237 * Must be called at splbio or in a fashion that prevents reentry. 2238 */ 2239static int 2240mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2241{ 2242 |
2124 debug("called"); | 2243 debug_called(2); |
2125 2126 /* status available? */ 2127 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) { 2128 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */ 2129 *status = MLX_V3_GET_STATUS(sc); /* get status */ 2130 2131 /* acknowledge completion */ 2132 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL); --- 6 unchanged lines hidden (view full) --- 2139/******************************************************************************** 2140 * Enable/disable interrupts as requested. (No acknowledge required) 2141 * 2142 * Must be called at splbio or in a fashion that prevents reentry. 2143 */ 2144static void 2145mlx_v3_intaction(struct mlx_softc *sc, int action) 2146{ | 2244 2245 /* status available? */ 2246 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) { 2247 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */ 2248 *status = MLX_V3_GET_STATUS(sc); /* get status */ 2249 2250 /* acknowledge completion */ 2251 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL); --- 6 unchanged lines hidden (view full) --- 2258/******************************************************************************** 2259 * Enable/disable interrupts as requested. (No acknowledge required) 2260 * 2261 * Must be called at splbio or in a fashion that prevents reentry. 2262 */ 2263static void 2264mlx_v3_intaction(struct mlx_softc *sc, int action) 2265{ |
2147 debug("called"); | 2266 debug_called(1); |
2148 2149 switch(action) { 2150 case MLX_INTACTION_DISABLE: 2151 MLX_V3_PUT_IER(sc, 0); 2152 sc->mlx_state &= ~MLX_STATE_INTEN; 2153 break; 2154 case MLX_INTACTION_ENABLE: 2155 MLX_V3_PUT_IER(sc, 1); 2156 sc->mlx_state |= MLX_STATE_INTEN; 2157 break; 2158 } 2159} 2160 | 2267 2268 switch(action) { 2269 case MLX_INTACTION_DISABLE: 2270 MLX_V3_PUT_IER(sc, 0); 2271 sc->mlx_state &= ~MLX_STATE_INTEN; 2272 break; 2273 case MLX_INTACTION_ENABLE: 2274 MLX_V3_PUT_IER(sc, 1); 2275 sc->mlx_state |= MLX_STATE_INTEN; 2276 break; 2277 } 2278} 2279 |
2280/******************************************************************************** 2281 * Poll for firmware error codes during controller initialisation. 2282 * Returns 0 if initialisation is complete, 1 if still in progress but no 2283 * error has been fetched, 2 if an error has been retrieved. 2284 */ 2285static int 2286mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) 2287{ 2288 u_int8_t fwerror; 2289 static int initted = 0; |
|
2161 | 2290 |
2291 debug_called(2); 2292 2293 /* first time around, clear any hardware completion status */ 2294 if (!initted) { 2295 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); 2296 DELAY(1000); 2297 initted = 1; 2298 } 2299 2300 /* init in progress? */ 2301 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY)) 2302 return(0); 2303 2304 /* test error value */ 2305 fwerror = MLX_V3_GET_FWERROR(sc); 2306 if (!(fwerror & MLX_V3_FWERROR_PEND)) 2307 return(1); 2308 2309 /* mask status pending bit, fetch status */ 2310 *error = fwerror & ~MLX_V3_FWERROR_PEND; 2311 *param1 = MLX_V3_GET_FWERROR_PARAM1(sc); 2312 *param2 = MLX_V3_GET_FWERROR_PARAM2(sc); 2313 2314 /* acknowledge */ 2315 MLX_V3_PUT_FWERROR(sc, 0); 2316 2317 return(2); 2318} 2319 |
|
2162/******************************************************************************** 2163 ******************************************************************************** 2164 Type 4 interface accessor methods 2165 ******************************************************************************** 2166 ********************************************************************************/ 2167 2168/******************************************************************************** 2169 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2170 * (the controller is not ready to take a command). 2171 * 2172 * Must be called at splbio or in a fashion that prevents reentry. 2173 */ 2174static int 2175mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2176{ 2177 int i; 2178 | 2320/******************************************************************************** 2321 ******************************************************************************** 2322 Type 4 interface accessor methods 2323 ******************************************************************************** 2324 ********************************************************************************/ 2325 2326/******************************************************************************** 2327 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2328 * (the controller is not ready to take a command). 2329 * 2330 * Must be called at splbio or in a fashion that prevents reentry. 2331 */ 2332static int 2333mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2334{ 2335 int i; 2336 |
2179 debug("called"); | 2337 debug_called(2); |
2180 2181 /* ready for our command? */ 2182 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) { 2183 /* copy mailbox data to window */ 2184 for (i = 0; i < 13; i++) 2185 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2186 | 2338 2339 /* ready for our command? */ 2340 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) { 2341 /* copy mailbox data to window */ 2342 for (i = 0; i < 13; i++) 2343 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2344 |
2345 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */ 2346 bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH, 2347 BUS_SPACE_BARRIER_WRITE); 2348 |
|
2187 /* post command */ 2188 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD); 2189 return(1); 2190 } 2191 return(0); 2192} 2193 2194/******************************************************************************** 2195 * See if a command has been completed, if so acknowledge its completion 2196 * and recover the slot number and status code. 2197 * 2198 * Must be called at splbio or in a fashion that prevents reentry. 2199 */ 2200static int 2201mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2202{ 2203 | 2349 /* post command */ 2350 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD); 2351 return(1); 2352 } 2353 return(0); 2354} 2355 2356/******************************************************************************** 2357 * See if a command has been completed, if so acknowledge its completion 2358 * and recover the slot number and status code. 2359 * 2360 * Must be called at splbio or in a fashion that prevents reentry. 2361 */ 2362static int 2363mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2364{ 2365 |
2204 debug("called"); | 2366 debug_called(2); |
2205 2206 /* status available? */ 2207 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) { 2208 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */ 2209 *status = MLX_V4_GET_STATUS(sc); /* get status */ 2210 2211 /* acknowledge completion */ 2212 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK); --- 6 unchanged lines hidden (view full) --- 2219/******************************************************************************** 2220 * Enable/disable interrupts as requested. 2221 * 2222 * Must be called at splbio or in a fashion that prevents reentry. 2223 */ 2224static void 2225mlx_v4_intaction(struct mlx_softc *sc, int action) 2226{ | 2367 2368 /* status available? */ 2369 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) { 2370 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */ 2371 *status = MLX_V4_GET_STATUS(sc); /* get status */ 2372 2373 /* acknowledge completion */ 2374 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK); --- 6 unchanged lines hidden (view full) --- 2381/******************************************************************************** 2382 * Enable/disable interrupts as requested. 2383 * 2384 * Must be called at splbio or in a fashion that prevents reentry. 2385 */ 2386static void 2387mlx_v4_intaction(struct mlx_softc *sc, int action) 2388{ |
2227 debug("called"); | 2389 debug_called(1); |
2228 2229 switch(action) { 2230 case MLX_INTACTION_DISABLE: 2231 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT); 2232 sc->mlx_state &= ~MLX_STATE_INTEN; 2233 break; 2234 case MLX_INTACTION_ENABLE: 2235 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT); 2236 sc->mlx_state |= MLX_STATE_INTEN; 2237 break; 2238 } 2239} 2240 | 2390 2391 switch(action) { 2392 case MLX_INTACTION_DISABLE: 2393 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT); 2394 sc->mlx_state &= ~MLX_STATE_INTEN; 2395 break; 2396 case MLX_INTACTION_ENABLE: 2397 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT); 2398 sc->mlx_state |= MLX_STATE_INTEN; 2399 break; 2400 } 2401} 2402 |
2403/******************************************************************************** 2404 * Poll for firmware error codes during controller initialisation. 2405 * Returns 0 if initialisation is complete, 1 if still in progress but no 2406 * error has been fetched, 2 if an error has been retrieved. 2407 */ 2408static int 2409mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) 2410{ 2411 u_int8_t fwerror; 2412 static int initted = 0; |
|
2241 | 2413 |
2414 debug_called(2); 2415 2416 /* first time around, clear any hardware completion status */ 2417 if (!initted) { 2418 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); 2419 DELAY(1000); 2420 initted = 1; 2421 } 2422 2423 /* init in progress? */ 2424 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY)) 2425 return(0); 2426 2427 /* test error value */ 2428 fwerror = MLX_V4_GET_FWERROR(sc); 2429 if (!(fwerror & MLX_V4_FWERROR_PEND)) 2430 return(1); 2431 2432 /* mask status pending bit, fetch status */ 2433 *error = fwerror & ~MLX_V4_FWERROR_PEND; 2434 *param1 = MLX_V4_GET_FWERROR_PARAM1(sc); 2435 *param2 = MLX_V4_GET_FWERROR_PARAM2(sc); 2436 2437 /* acknowledge */ 2438 MLX_V4_PUT_FWERROR(sc, 0); 2439 2440 return(2); 2441} 2442 |
|
2242/******************************************************************************** 2243 ******************************************************************************** 2244 Type 5 interface accessor methods 2245 ******************************************************************************** 2246 ********************************************************************************/ 2247 2248/******************************************************************************** 2249 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2250 * (the controller is not ready to take a command). 2251 * 2252 * Must be called at splbio or in a fashion that prevents reentry. 2253 */ 2254static int 2255mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2256{ 2257 int i; | 2443/******************************************************************************** 2444 ******************************************************************************** 2445 Type 5 interface accessor methods 2446 ******************************************************************************** 2447 ********************************************************************************/ 2448 2449/******************************************************************************** 2450 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2451 * (the controller is not ready to take a command). 2452 * 2453 * Must be called at splbio or in a fashion that prevents reentry. 2454 */ 2455static int 2456mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2457{ 2458 int i; |
2258 2259 debug("called"); | |
2260 | 2459 |
2460 debug_called(2); 2461 |
|
2261 /* ready for our command? */ 2262 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) { 2263 /* copy mailbox data to window */ 2264 for (i = 0; i < 13; i++) 2265 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); | 2462 /* ready for our command? */ 2463 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) { 2464 /* copy mailbox data to window */ 2465 for (i = 0; i < 13; i++) 2466 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); |
2266 | 2467 |
2267 /* post command */ 2268 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD); 2269 return(1); 2270 } 2271 return(0); 2272} 2273 2274/******************************************************************************** 2275 * See if a command has been completed, if so acknowledge its completion 2276 * and recover the slot number and status code. 2277 * 2278 * Must be called at splbio or in a fashion that prevents reentry. 2279 */ 2280static int 2281mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2282{ 2283 | 2468 /* post command */ 2469 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD); 2470 return(1); 2471 } 2472 return(0); 2473} 2474 2475/******************************************************************************** 2476 * See if a command has been completed, if so acknowledge its completion 2477 * and recover the slot number and status code. 2478 * 2479 * Must be called at splbio or in a fashion that prevents reentry. 2480 */ 2481static int 2482mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2483{ 2484 |
2284 debug("called"); | 2485 debug_called(2); |
2285 2286 /* status available? */ 2287 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) { 2288 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */ 2289 *status = MLX_V5_GET_STATUS(sc); /* get status */ 2290 2291 /* acknowledge completion */ 2292 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK); --- 6 unchanged lines hidden (view full) --- 2299/******************************************************************************** 2300 * Enable/disable interrupts as requested. 2301 * 2302 * Must be called at splbio or in a fashion that prevents reentry. 2303 */ 2304static void 2305mlx_v5_intaction(struct mlx_softc *sc, int action) 2306{ | 2486 2487 /* status available? */ 2488 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) { 2489 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */ 2490 *status = MLX_V5_GET_STATUS(sc); /* get status */ 2491 2492 /* acknowledge completion */ 2493 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK); --- 6 unchanged lines hidden (view full) --- 2500/******************************************************************************** 2501 * Enable/disable interrupts as requested. 2502 * 2503 * Must be called at splbio or in a fashion that prevents reentry. 2504 */ 2505static void 2506mlx_v5_intaction(struct mlx_softc *sc, int action) 2507{ |
2307 debug("called"); | 2508 debug_called(1); |
2308 2309 switch(action) { 2310 case MLX_INTACTION_DISABLE: | 2509 2510 switch(action) { 2511 case MLX_INTACTION_DISABLE: |
2311 MLX_V5_PUT_IER(sc, MLX_V5_IER_DISINT); | 2512 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT); |
2312 sc->mlx_state &= ~MLX_STATE_INTEN; 2313 break; 2314 case MLX_INTACTION_ENABLE: | 2513 sc->mlx_state &= ~MLX_STATE_INTEN; 2514 break; 2515 case MLX_INTACTION_ENABLE: |
2315 MLX_V5_PUT_IER(sc, 0); | 2516 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT); |
2316 sc->mlx_state |= MLX_STATE_INTEN; 2317 break; 2318 } 2319} 2320 | 2517 sc->mlx_state |= MLX_STATE_INTEN; 2518 break; 2519 } 2520} 2521 |
2522/******************************************************************************** 2523 * Poll for firmware error codes during controller initialisation. 2524 * Returns 0 if initialisation is complete, 1 if still in progress but no 2525 * error has been fetched, 2 if an error has been retrieved. 2526 */ 2527static int 2528mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) 2529{ 2530 u_int8_t fwerror; 2531 static int initted = 0; |
|
2321 | 2532 |
2533 debug_called(2); 2534 2535 /* first time around, clear any hardware completion status */ 2536 if (!initted) { 2537 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); 2538 DELAY(1000); 2539 initted = 1; 2540 } 2541 2542 /* init in progress? */ 2543 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE) 2544 return(0); 2545 2546 /* test for error value */ 2547 fwerror = MLX_V5_GET_FWERROR(sc); 2548 if (!(fwerror & MLX_V5_FWERROR_PEND)) 2549 return(1); 2550 2551 /* mask status pending bit, fetch status */ 2552 *error = fwerror & ~MLX_V5_FWERROR_PEND; 2553 *param1 = MLX_V5_GET_FWERROR_PARAM1(sc); 2554 *param2 = MLX_V5_GET_FWERROR_PARAM2(sc); 2555 2556 /* acknowledge */ 2557 MLX_V5_PUT_FWERROR(sc, 0xff); 2558 2559 return(2); 2560} 2561 |
|
2322/******************************************************************************** 2323 ******************************************************************************** 2324 Debugging 2325 ******************************************************************************** 2326 ********************************************************************************/ 2327 2328/******************************************************************************** 2329 * Return a status message describing (mc) --- 8 unchanged lines hidden (view full) --- 2338 "attempt to rebuild online drive", /* 06 */ 2339 "new disk failed during rebuild", /* 07 */ 2340 "invalid channel/target", /* 08 */ 2341 "rebuild/check already in progress", /* 09 */ 2342 "one or more disks are dead", /* 10 */ 2343 "invalid or non-redundant drive", /* 11 */ 2344 "channel is busy", /* 12 */ 2345 "channel is not stopped", /* 13 */ | 2562/******************************************************************************** 2563 ******************************************************************************** 2564 Debugging 2565 ******************************************************************************** 2566 ********************************************************************************/ 2567 2568/******************************************************************************** 2569 * Return a status message describing (mc) --- 8 unchanged lines hidden (view full) --- 2578 "attempt to rebuild online drive", /* 06 */ 2579 "new disk failed during rebuild", /* 07 */ 2580 "invalid channel/target", /* 08 */ 2581 "rebuild/check already in progress", /* 09 */ 2582 "one or more disks are dead", /* 10 */ 2583 "invalid or non-redundant drive", /* 11 */ 2584 "channel is busy", /* 12 */ 2585 "channel is not stopped", /* 13 */ |
2586 "rebuild successfully terminated", /* 14 */ 2587 "unsupported command", /* 15 */ 2588 "check condition received", /* 16 */ 2589 "device is busy", /* 17 */ 2590 "selection or command timeout", /* 18 */ 2591 "command terminated abnormally", /* 19 */ 2592 "" |
|
2346}; 2347 2348static struct 2349{ 2350 int command; 2351 u_int16_t status; 2352 int msg; 2353} mlx_messages[] = { | 2593}; 2594 2595static struct 2596{ 2597 int command; 2598 u_int16_t status; 2599 int msg; 2600} mlx_messages[] = { |
2354 {MLX_CMD_READOLDSG, 0x0001, 1}, 2355 {MLX_CMD_READOLDSG, 0x0002, 1}, 2356 {MLX_CMD_READOLDSG, 0x0105, 3}, 2357 {MLX_CMD_READOLDSG, 0x010c, 4}, 2358 {MLX_CMD_WRITEOLDSG, 0x0001, 1}, 2359 {MLX_CMD_WRITEOLDSG, 0x0002, 1}, 2360 {MLX_CMD_WRITEOLDSG, 0x0105, 3}, | 2601 {MLX_CMD_READSG, 0x0001, 1}, 2602 {MLX_CMD_READSG, 0x0002, 1}, 2603 {MLX_CMD_READSG, 0x0105, 3}, 2604 {MLX_CMD_READSG, 0x010c, 4}, 2605 {MLX_CMD_WRITESG, 0x0001, 1}, 2606 {MLX_CMD_WRITESG, 0x0002, 1}, 2607 {MLX_CMD_WRITESG, 0x0105, 3}, 2608 {MLX_CMD_READSG_OLD, 0x0001, 1}, 2609 {MLX_CMD_READSG_OLD, 0x0002, 1}, 2610 {MLX_CMD_READSG_OLD, 0x0105, 3}, 2611 {MLX_CMD_WRITESG_OLD, 0x0001, 1}, 2612 {MLX_CMD_WRITESG_OLD, 0x0002, 1}, 2613 {MLX_CMD_WRITESG_OLD, 0x0105, 3}, |
2361 {MLX_CMD_LOGOP, 0x0105, 5}, 2362 {MLX_CMD_REBUILDASYNC, 0x0002, 6}, 2363 {MLX_CMD_REBUILDASYNC, 0x0004, 7}, 2364 {MLX_CMD_REBUILDASYNC, 0x0105, 8}, 2365 {MLX_CMD_REBUILDASYNC, 0x0106, 9}, | 2614 {MLX_CMD_LOGOP, 0x0105, 5}, 2615 {MLX_CMD_REBUILDASYNC, 0x0002, 6}, 2616 {MLX_CMD_REBUILDASYNC, 0x0004, 7}, 2617 {MLX_CMD_REBUILDASYNC, 0x0105, 8}, 2618 {MLX_CMD_REBUILDASYNC, 0x0106, 9}, |
2619 {MLX_CMD_REBUILDASYNC, 0x0107, 14}, |
|
2366 {MLX_CMD_CHECKASYNC, 0x0002, 10}, 2367 {MLX_CMD_CHECKASYNC, 0x0105, 11}, 2368 {MLX_CMD_CHECKASYNC, 0x0106, 9}, 2369 {MLX_CMD_STOPCHANNEL, 0x0106, 12}, 2370 {MLX_CMD_STOPCHANNEL, 0x0105, 8}, 2371 {MLX_CMD_STARTCHANNEL, 0x0005, 13}, 2372 {MLX_CMD_STARTCHANNEL, 0x0105, 8}, | 2620 {MLX_CMD_CHECKASYNC, 0x0002, 10}, 2621 {MLX_CMD_CHECKASYNC, 0x0105, 11}, 2622 {MLX_CMD_CHECKASYNC, 0x0106, 9}, 2623 {MLX_CMD_STOPCHANNEL, 0x0106, 12}, 2624 {MLX_CMD_STOPCHANNEL, 0x0105, 8}, 2625 {MLX_CMD_STARTCHANNEL, 0x0005, 13}, 2626 {MLX_CMD_STARTCHANNEL, 0x0105, 8}, |
2627 {MLX_CMD_DIRECT_CDB, 0x0002, 16}, 2628 {MLX_CMD_DIRECT_CDB, 0x0008, 17}, 2629 {MLX_CMD_DIRECT_CDB, 0x000e, 18}, 2630 {MLX_CMD_DIRECT_CDB, 0x000f, 19}, 2631 {MLX_CMD_DIRECT_CDB, 0x0105, 8}, 2632 2633 {0, 0x0104, 14}, |
|
2373 {-1, 0, 0} 2374}; 2375 2376static char * 2377mlx_diagnose_command(struct mlx_command *mc) 2378{ 2379 static char unkmsg[80]; 2380 int i; 2381 2382 /* look up message in table */ 2383 for (i = 0; mlx_messages[i].command != -1; i++) | 2634 {-1, 0, 0} 2635}; 2636 2637static char * 2638mlx_diagnose_command(struct mlx_command *mc) 2639{ 2640 static char unkmsg[80]; 2641 int i; 2642 2643 /* look up message in table */ 2644 for (i = 0; mlx_messages[i].command != -1; i++) |
2384 if ((mc->mc_mailbox[0] == mlx_messages[i].command) && | 2645 if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) && |
2385 (mc->mc_status == mlx_messages[i].status)) 2386 return(mlx_status_messages[mlx_messages[i].msg]); 2387 2388 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]); 2389 return(unkmsg); 2390} 2391 2392/******************************************************************************* | 2646 (mc->mc_status == mlx_messages[i].status)) 2647 return(mlx_status_messages[mlx_messages[i].msg]); 2648 2649 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]); 2650 return(unkmsg); 2651} 2652 2653/******************************************************************************* |
2393 * Return a string describing the controller (hwid) | 2654 * Print a string describing the controller (sc) |
2394 */ 2395static struct 2396{ 2397 int hwid; 2398 char *name; 2399} mlx_controller_names[] = { 2400 {0x01, "960P/PD"}, 2401 {0x02, "960PL"}, --- 20 unchanged lines hidden (view full) --- 2422 model = mlx_controller_names[i].name; 2423 break; 2424 } 2425 } 2426 if (model == NULL) { 2427 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff); 2428 model = buf; 2429 } | 2655 */ 2656static struct 2657{ 2658 int hwid; 2659 char *name; 2660} mlx_controller_names[] = { 2661 {0x01, "960P/PD"}, 2662 {0x02, "960PL"}, --- 20 unchanged lines hidden (view full) --- 2683 model = mlx_controller_names[i].name; 2684 break; 2685 } 2686 } 2687 if (model == NULL) { 2688 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff); 2689 model = buf; 2690 } |
2430 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%d, %dMB RAM\n", | 2691 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n", |
2431 model, 2432 sc->mlx_enq2->me_actual_channels, 2433 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "", 2434 sc->mlx_enq2->me_firmware_id & 0xff, 2435 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff, 2436 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff, 2437 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff, 2438 sc->mlx_enq2->me_mem_size / (1024 * 1024)); --- 32 unchanged lines hidden (view full) --- 2471 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build); 2472 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type); 2473 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features, 2474 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n"); 2475 2476 } 2477} 2478 | 2692 model, 2693 sc->mlx_enq2->me_actual_channels, 2694 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "", 2695 sc->mlx_enq2->me_firmware_id & 0xff, 2696 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff, 2697 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff, 2698 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff, 2699 sc->mlx_enq2->me_mem_size / (1024 * 1024)); --- 32 unchanged lines hidden (view full) --- 2732 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build); 2733 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type); 2734 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features, 2735 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n"); 2736 2737 } 2738} 2739 |
2740/******************************************************************************* 2741 * Emit a string describing the firmware handshake status code, and return a flag 2742 * indicating whether the code represents a fatal error. 2743 * 2744 * Error code interpretations are from the Linux driver, and don't directly match 2745 * the messages printed by Mylex's BIOS. This may change if documentation on the 2746 * codes is forthcoming. 2747 */ 2748static int 2749mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2) 2750{ 2751 switch(error) { 2752 case 0x00: 2753 device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1); 2754 break; 2755 case 0x08: 2756 /* we could be neater about this and give some indication when we receive more of them */ 2757 if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) { 2758 device_printf(sc->mlx_dev, "spinning up drives...\n"); 2759 sc->mlx_flags |= MLX_SPINUP_REPORTED; 2760 } 2761 break; 2762 case 0x30: 2763 device_printf(sc->mlx_dev, "configuration checksum error\n"); 2764 break; 2765 case 0x60: 2766 device_printf(sc->mlx_dev, "mirror race recovery failed\n"); 2767 break; 2768 case 0x70: 2769 device_printf(sc->mlx_dev, "mirror race recovery in progress\n"); 2770 break; 2771 case 0x90: 2772 device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1); 2773 break; 2774 case 0xa0: 2775 device_printf(sc->mlx_dev, "logical drive installation aborted\n"); 2776 break; 2777 case 0xb0: 2778 device_printf(sc->mlx_dev, "mirror race on a critical system drive\n"); 2779 break; 2780 case 0xd0: 2781 device_printf(sc->mlx_dev, "new controller configuration found\n"); 2782 break; 2783 case 0xf0: 2784 device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n"); 2785 return(1); 2786 default: 2787 device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2); 2788 break; 2789 } 2790 return(0); 2791} 2792 |
|
2479/******************************************************************************** 2480 ******************************************************************************** 2481 Utility Functions 2482 ******************************************************************************** 2483 ********************************************************************************/ 2484 2485/******************************************************************************** 2486 * Find the disk whose unit number is (unit) on this controller --- 17 unchanged lines hidden --- | 2793/******************************************************************************** 2794 ******************************************************************************** 2795 Utility Functions 2796 ******************************************************************************** 2797 ********************************************************************************/ 2798 2799/******************************************************************************** 2800 * Find the disk whose unit number is (unit) on this controller --- 17 unchanged lines hidden --- |