1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 *
| 1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 *
|
37 38#ifdef TWE_DEBUG 39#define debug(level, fmt, args...) \ 40 do { \ 41 if (level <= TWE_DEBUG) printf("%s: " fmt "\n", __func__ , ##args); \ 42 } while(0) 43#define debug_called(level) \ 44 do { \ 45 if (level <= TWE_DEBUG) printf("%s: called\n", __func__); \ 46 } while(0) 47#else 48#define debug(level, fmt, args...) 49#define debug_called(level) 50#endif 51 52/* 53 * Structure describing a logical unit as attached to the controller 54 */ 55struct twe_drive 56{ 57 /* unit properties */ 58 u_int32_t td_size; 59 int td_cylinders; 60 int td_heads; 61 int td_sectors; 62 int td_sys_unit; /* device unit number */ 63 int td_twe_unit; /* index into sc->twe_drive[] */ 64 65 /* unit state and type */ 66 u_int8_t td_state; 67 u_int8_t td_type; 68 69 /* handle for attached driver */ 70 device_t td_disk; 71}; 72 73/* 74 * Per-command control structure. 75 * 76 * Note that due to alignment constraints on the tc_command field, this *must* be 64-byte aligned. 77 * We achieve this by placing the command at the beginning of the structure, and using malloc() 78 * to allocate each structure. 79 */ 80struct twe_request 81{ 82 int tr_tag; 83 /* command payload */ 84 void *tr_data; /* data buffer */ 85 void *tr_realdata; /* copy of real data buffer pointer for alignment fixup */ 86 size_t tr_length; 87 88 TAILQ_ENTRY(twe_request) tr_link; /* list linkage */ 89 struct twe_softc *tr_sc; /* controller that owns us */ 90 int tr_status; /* command status */ 91#define TWE_CMD_SETUP 0 /* being assembled */ 92#define TWE_CMD_BUSY 1 /* submitted to controller */ 93#define TWE_CMD_COMPLETE 2 /* completed by controller (maybe with error) */ 94 int tr_flags; 95#define TWE_CMD_DATAIN (1<<0) 96#define TWE_CMD_DATAOUT (1<<1) 97#define TWE_CMD_ALIGNBUF (1<<2) /* data in bio is misaligned, have to copy to/from private buffer */ 98#define TWE_CMD_SLEEPER (1<<3) /* owner is sleeping on this command */ 99#define TWE_CMD_IMMEDIATE (1<<4) /* immediate request */ 100#define TWE_CMD_MAPPED (1<<5) 101 void (* tr_complete)(struct twe_request *tr); /* completion handler */ 102 void *tr_private; /* submitter-private data or wait channel */ 103 104 TWE_PLATFORM_REQUEST /* platform-specific request elements */ 105}; 106 107#define TWE_FIND_COMMAND(tr) \ 108 (TWE_Command *)((u_int8_t *)(tr)->tr_sc->twe_cmd + \ 109 ((tr)->tr_tag * sizeof(TWE_Command))) 110#define TWE_FIND_COMMANDPHYS(tr) ((tr)->tr_sc->twe_cmdphys + \ 111 ((tr)->tr_tag * sizeof(TWE_Command))) 112 113/* 114 * Per-controller state. 115 */ 116struct twe_softc 117{ 118 /* controller queues and arrays */ 119 TAILQ_HEAD(, twe_request) twe_free; /* command structures available for reuse */ 120 twe_bioq twe_bioq; /* outstanding I/O operations */ 121 TAILQ_HEAD(, twe_request) twe_ready; /* requests ready for the controller */ 122 TAILQ_HEAD(, twe_request) twe_busy; /* requests busy in the controller */ 123 TAILQ_HEAD(, twe_request) twe_complete; /* active commands (busy or waiting for completion) */ 124 struct twe_request *twe_lookup[TWE_Q_LENGTH]; /* commands indexed by request ID */ 125 struct twe_drive twe_drive[TWE_MAX_UNITS]; /* attached drives */ 126 127 /* asynchronous event handling */ 128 u_int16_t twe_aen_queue[TWE_Q_LENGTH]; /* AENs queued for userland tool(s) */ 129 int twe_aen_head, twe_aen_tail; /* ringbuffer pointers for AEN queue */ 130 int twe_wait_aen; /* wait-for-aen notification */ 131 132 /* controller status */ 133 int twe_state; 134#define TWE_STATE_INTEN (1<<0) /* interrupts have been enabled */ 135#define TWE_STATE_SHUTDOWN (1<<1) /* controller is shut down */ 136#define TWE_STATE_OPEN (1<<2) /* control device is open */ 137#define TWE_STATE_SUSPEND (1<<3) /* controller is suspended */ 138#define TWE_STATE_FRZN (1<<4) 139 int twe_host_id; 140 struct twe_qstat twe_qstat[TWEQ_COUNT]; /* queue statistics */ 141 142 TWE_PLATFORM_SOFTC /* platform-specific softc elements */ 143}; 144 145/* 146 * Interface betwen driver core and platform-dependant code. 147 */ 148extern int twe_setup(struct twe_softc *sc); /* do early driver/controller setup */ 149extern void twe_init(struct twe_softc *sc); /* init controller */ 150extern void twe_deinit(struct twe_softc *sc); /* stop controller */ 151extern void twe_intr(struct twe_softc *sc); /* hardware interrupt signalled */ 152extern void twe_startio(struct twe_softc *sc); 153extern int twe_start(struct twe_request *tr); 154extern int twe_dump_blocks(struct twe_softc *sc, int unit, /* crashdump block write */ 155 u_int32_t lba, void *data, int nblks); 156extern int twe_ioctl(struct twe_softc *sc, int cmd, 157 void *addr); /* handle user request */ 158extern void twe_describe_controller(struct twe_softc *sc); /* print controller info */ 159extern void twe_print_controller(struct twe_softc *sc); 160extern void twe_enable_interrupts(struct twe_softc *sc); /* enable controller interrupts */ 161extern void twe_disable_interrupts(struct twe_softc *sc); /* disable controller interrupts */ 162 163extern int twe_attach_drive(struct twe_softc *sc, 164 struct twe_drive *dr); /* attach drive when found in twe_init */ 165extern int twe_detach_drive(struct twe_softc *sc, 166 int unit); /* detach drive */ 167extern void twe_clear_pci_parity_error(struct twe_softc *sc); 168extern void twe_clear_pci_abort(struct twe_softc *sc); 169extern void twed_intr(twe_bio *bp); /* return bio from core */ 170extern struct twe_request *twe_allocate_request(struct twe_softc *sc, int tag); /* allocate request structure */ 171extern void twe_free_request(struct twe_request *tr); /* free request structure */ 172extern int twe_map_request(struct twe_request *tr); /* make request visible to controller, do s/g */ 173extern void twe_unmap_request(struct twe_request *tr); /* cleanup after transfer, unmap */ 174 175/******************************************************************************** 176 * Queue primitives 177 */ 178#define TWEQ_ADD(sc, qname) \ 179 do { \ 180 struct twe_qstat *qs = &(sc)->twe_qstat[qname]; \ 181 \ 182 qs->q_length++; \ 183 if (qs->q_length > qs->q_max) \ 184 qs->q_max = qs->q_length; \ 185 } while(0) 186 187#define TWEQ_REMOVE(sc, qname) \ 188 do { \ 189 struct twe_qstat *qs = &(sc)->twe_qstat[qname]; \ 190 \ 191 qs->q_length--; \ 192 if (qs->q_length < qs->q_min) \ 193 qs->q_min = qs->q_length; \ 194 } while(0); 195 196#define TWEQ_INIT(sc, qname) \ 197 do { \ 198 sc->twe_qstat[qname].q_length = 0; \ 199 sc->twe_qstat[qname].q_max = 0; \ 200 sc->twe_qstat[qname].q_min = 0xFFFFFFFF; \ 201 } while(0) 202 203 204#define TWEQ_REQUEST_QUEUE(name, index) \ 205static __inline void \ 206twe_initq_ ## name (struct twe_softc *sc) \ 207{ \ 208 TAILQ_INIT(&sc->twe_ ## name); \ 209 TWEQ_INIT(sc, index); \ 210} \ 211static __inline void \ 212twe_enqueue_ ## name (struct twe_request *tr) \ 213{ \ 214 int s; \ 215 \ 216 s = splbio(); \ 217 TAILQ_INSERT_TAIL(&tr->tr_sc->twe_ ## name, tr, tr_link); \ 218 TWEQ_ADD(tr->tr_sc, index); \ 219 splx(s); \ 220} \ 221static __inline void \ 222twe_requeue_ ## name (struct twe_request *tr) \ 223{ \ 224 int s; \ 225 \ 226 s = splbio(); \ 227 TAILQ_INSERT_HEAD(&tr->tr_sc->twe_ ## name, tr, tr_link); \ 228 TWEQ_ADD(tr->tr_sc, index); \ 229 splx(s); \ 230} \ 231static __inline struct twe_request * \ 232twe_dequeue_ ## name (struct twe_softc *sc) \ 233{ \ 234 struct twe_request *tr; \ 235 int s; \ 236 \ 237 s = splbio(); \ 238 if ((tr = TAILQ_FIRST(&sc->twe_ ## name)) != NULL) { \ 239 TAILQ_REMOVE(&sc->twe_ ## name, tr, tr_link); \ 240 TWEQ_REMOVE(sc, index); \ 241 } \ 242 splx(s); \ 243 return(tr); \ 244} \ 245static __inline void \ 246twe_remove_ ## name (struct twe_request *tr) \ 247{ \ 248 int s; \ 249 \ 250 s = splbio(); \ 251 TAILQ_REMOVE(&tr->tr_sc->twe_ ## name, tr, tr_link); \ 252 TWEQ_REMOVE(tr->tr_sc, index); \ 253 splx(s); \ 254} 255 256TWEQ_REQUEST_QUEUE(free, TWEQ_FREE) 257TWEQ_REQUEST_QUEUE(ready, TWEQ_READY) 258TWEQ_REQUEST_QUEUE(busy, TWEQ_BUSY) 259TWEQ_REQUEST_QUEUE(complete, TWEQ_COMPLETE) 260 261/* 262 * outstanding bio queue 263 */ 264static __inline void 265twe_initq_bio(struct twe_softc *sc) 266{ 267 TWE_BIO_QINIT(sc->twe_bioq); 268 TWEQ_INIT(sc, TWEQ_BIO); 269} 270 271static __inline void 272twe_enqueue_bio(struct twe_softc *sc, twe_bio *bp) 273{ 274 int s; 275 276 s = splbio(); 277 TWE_BIO_QINSERT(sc->twe_bioq, bp); 278 TWEQ_ADD(sc, TWEQ_BIO); 279 splx(s); 280} 281 282static __inline twe_bio * 283twe_dequeue_bio(struct twe_softc *sc) 284{ 285 int s; 286 twe_bio *bp; 287 288 s = splbio(); 289 if ((bp = TWE_BIO_QFIRST(sc->twe_bioq)) != NULL) { 290 TWE_BIO_QREMOVE(sc->twe_bioq, bp); 291 TWEQ_REMOVE(sc, TWEQ_BIO); 292 } 293 splx(s); 294 return(bp); 295}
| 35 36#ifdef TWE_DEBUG 37#define debug(level, fmt, args...) \ 38 do { \ 39 if (level <= TWE_DEBUG) printf("%s: " fmt "\n", __func__ , ##args); \ 40 } while(0) 41#define debug_called(level) \ 42 do { \ 43 if (level <= TWE_DEBUG) printf("%s: called\n", __func__); \ 44 } while(0) 45#else 46#define debug(level, fmt, args...) 47#define debug_called(level) 48#endif 49 50/* 51 * Structure describing a logical unit as attached to the controller 52 */ 53struct twe_drive 54{ 55 /* unit properties */ 56 u_int32_t td_size; 57 int td_cylinders; 58 int td_heads; 59 int td_sectors; 60 int td_sys_unit; /* device unit number */ 61 int td_twe_unit; /* index into sc->twe_drive[] */ 62 63 /* unit state and type */ 64 u_int8_t td_state; 65 u_int8_t td_type; 66 67 /* handle for attached driver */ 68 device_t td_disk; 69}; 70 71/* 72 * Per-command control structure. 73 * 74 * Note that due to alignment constraints on the tc_command field, this *must* be 64-byte aligned. 75 * We achieve this by placing the command at the beginning of the structure, and using malloc() 76 * to allocate each structure. 77 */ 78struct twe_request 79{ 80 int tr_tag; 81 /* command payload */ 82 void *tr_data; /* data buffer */ 83 void *tr_realdata; /* copy of real data buffer pointer for alignment fixup */ 84 size_t tr_length; 85 86 TAILQ_ENTRY(twe_request) tr_link; /* list linkage */ 87 struct twe_softc *tr_sc; /* controller that owns us */ 88 int tr_status; /* command status */ 89#define TWE_CMD_SETUP 0 /* being assembled */ 90#define TWE_CMD_BUSY 1 /* submitted to controller */ 91#define TWE_CMD_COMPLETE 2 /* completed by controller (maybe with error) */ 92 int tr_flags; 93#define TWE_CMD_DATAIN (1<<0) 94#define TWE_CMD_DATAOUT (1<<1) 95#define TWE_CMD_ALIGNBUF (1<<2) /* data in bio is misaligned, have to copy to/from private buffer */ 96#define TWE_CMD_SLEEPER (1<<3) /* owner is sleeping on this command */ 97#define TWE_CMD_IMMEDIATE (1<<4) /* immediate request */ 98#define TWE_CMD_MAPPED (1<<5) 99 void (* tr_complete)(struct twe_request *tr); /* completion handler */ 100 void *tr_private; /* submitter-private data or wait channel */ 101 102 TWE_PLATFORM_REQUEST /* platform-specific request elements */ 103}; 104 105#define TWE_FIND_COMMAND(tr) \ 106 (TWE_Command *)((u_int8_t *)(tr)->tr_sc->twe_cmd + \ 107 ((tr)->tr_tag * sizeof(TWE_Command))) 108#define TWE_FIND_COMMANDPHYS(tr) ((tr)->tr_sc->twe_cmdphys + \ 109 ((tr)->tr_tag * sizeof(TWE_Command))) 110 111/* 112 * Per-controller state. 113 */ 114struct twe_softc 115{ 116 /* controller queues and arrays */ 117 TAILQ_HEAD(, twe_request) twe_free; /* command structures available for reuse */ 118 twe_bioq twe_bioq; /* outstanding I/O operations */ 119 TAILQ_HEAD(, twe_request) twe_ready; /* requests ready for the controller */ 120 TAILQ_HEAD(, twe_request) twe_busy; /* requests busy in the controller */ 121 TAILQ_HEAD(, twe_request) twe_complete; /* active commands (busy or waiting for completion) */ 122 struct twe_request *twe_lookup[TWE_Q_LENGTH]; /* commands indexed by request ID */ 123 struct twe_drive twe_drive[TWE_MAX_UNITS]; /* attached drives */ 124 125 /* asynchronous event handling */ 126 u_int16_t twe_aen_queue[TWE_Q_LENGTH]; /* AENs queued for userland tool(s) */ 127 int twe_aen_head, twe_aen_tail; /* ringbuffer pointers for AEN queue */ 128 int twe_wait_aen; /* wait-for-aen notification */ 129 130 /* controller status */ 131 int twe_state; 132#define TWE_STATE_INTEN (1<<0) /* interrupts have been enabled */ 133#define TWE_STATE_SHUTDOWN (1<<1) /* controller is shut down */ 134#define TWE_STATE_OPEN (1<<2) /* control device is open */ 135#define TWE_STATE_SUSPEND (1<<3) /* controller is suspended */ 136#define TWE_STATE_FRZN (1<<4) 137 int twe_host_id; 138 struct twe_qstat twe_qstat[TWEQ_COUNT]; /* queue statistics */ 139 140 TWE_PLATFORM_SOFTC /* platform-specific softc elements */ 141}; 142 143/* 144 * Interface betwen driver core and platform-dependant code. 145 */ 146extern int twe_setup(struct twe_softc *sc); /* do early driver/controller setup */ 147extern void twe_init(struct twe_softc *sc); /* init controller */ 148extern void twe_deinit(struct twe_softc *sc); /* stop controller */ 149extern void twe_intr(struct twe_softc *sc); /* hardware interrupt signalled */ 150extern void twe_startio(struct twe_softc *sc); 151extern int twe_start(struct twe_request *tr); 152extern int twe_dump_blocks(struct twe_softc *sc, int unit, /* crashdump block write */ 153 u_int32_t lba, void *data, int nblks); 154extern int twe_ioctl(struct twe_softc *sc, int cmd, 155 void *addr); /* handle user request */ 156extern void twe_describe_controller(struct twe_softc *sc); /* print controller info */ 157extern void twe_print_controller(struct twe_softc *sc); 158extern void twe_enable_interrupts(struct twe_softc *sc); /* enable controller interrupts */ 159extern void twe_disable_interrupts(struct twe_softc *sc); /* disable controller interrupts */ 160 161extern int twe_attach_drive(struct twe_softc *sc, 162 struct twe_drive *dr); /* attach drive when found in twe_init */ 163extern int twe_detach_drive(struct twe_softc *sc, 164 int unit); /* detach drive */ 165extern void twe_clear_pci_parity_error(struct twe_softc *sc); 166extern void twe_clear_pci_abort(struct twe_softc *sc); 167extern void twed_intr(twe_bio *bp); /* return bio from core */ 168extern struct twe_request *twe_allocate_request(struct twe_softc *sc, int tag); /* allocate request structure */ 169extern void twe_free_request(struct twe_request *tr); /* free request structure */ 170extern int twe_map_request(struct twe_request *tr); /* make request visible to controller, do s/g */ 171extern void twe_unmap_request(struct twe_request *tr); /* cleanup after transfer, unmap */ 172 173/******************************************************************************** 174 * Queue primitives 175 */ 176#define TWEQ_ADD(sc, qname) \ 177 do { \ 178 struct twe_qstat *qs = &(sc)->twe_qstat[qname]; \ 179 \ 180 qs->q_length++; \ 181 if (qs->q_length > qs->q_max) \ 182 qs->q_max = qs->q_length; \ 183 } while(0) 184 185#define TWEQ_REMOVE(sc, qname) \ 186 do { \ 187 struct twe_qstat *qs = &(sc)->twe_qstat[qname]; \ 188 \ 189 qs->q_length--; \ 190 if (qs->q_length < qs->q_min) \ 191 qs->q_min = qs->q_length; \ 192 } while(0); 193 194#define TWEQ_INIT(sc, qname) \ 195 do { \ 196 sc->twe_qstat[qname].q_length = 0; \ 197 sc->twe_qstat[qname].q_max = 0; \ 198 sc->twe_qstat[qname].q_min = 0xFFFFFFFF; \ 199 } while(0) 200 201 202#define TWEQ_REQUEST_QUEUE(name, index) \ 203static __inline void \ 204twe_initq_ ## name (struct twe_softc *sc) \ 205{ \ 206 TAILQ_INIT(&sc->twe_ ## name); \ 207 TWEQ_INIT(sc, index); \ 208} \ 209static __inline void \ 210twe_enqueue_ ## name (struct twe_request *tr) \ 211{ \ 212 int s; \ 213 \ 214 s = splbio(); \ 215 TAILQ_INSERT_TAIL(&tr->tr_sc->twe_ ## name, tr, tr_link); \ 216 TWEQ_ADD(tr->tr_sc, index); \ 217 splx(s); \ 218} \ 219static __inline void \ 220twe_requeue_ ## name (struct twe_request *tr) \ 221{ \ 222 int s; \ 223 \ 224 s = splbio(); \ 225 TAILQ_INSERT_HEAD(&tr->tr_sc->twe_ ## name, tr, tr_link); \ 226 TWEQ_ADD(tr->tr_sc, index); \ 227 splx(s); \ 228} \ 229static __inline struct twe_request * \ 230twe_dequeue_ ## name (struct twe_softc *sc) \ 231{ \ 232 struct twe_request *tr; \ 233 int s; \ 234 \ 235 s = splbio(); \ 236 if ((tr = TAILQ_FIRST(&sc->twe_ ## name)) != NULL) { \ 237 TAILQ_REMOVE(&sc->twe_ ## name, tr, tr_link); \ 238 TWEQ_REMOVE(sc, index); \ 239 } \ 240 splx(s); \ 241 return(tr); \ 242} \ 243static __inline void \ 244twe_remove_ ## name (struct twe_request *tr) \ 245{ \ 246 int s; \ 247 \ 248 s = splbio(); \ 249 TAILQ_REMOVE(&tr->tr_sc->twe_ ## name, tr, tr_link); \ 250 TWEQ_REMOVE(tr->tr_sc, index); \ 251 splx(s); \ 252} 253 254TWEQ_REQUEST_QUEUE(free, TWEQ_FREE) 255TWEQ_REQUEST_QUEUE(ready, TWEQ_READY) 256TWEQ_REQUEST_QUEUE(busy, TWEQ_BUSY) 257TWEQ_REQUEST_QUEUE(complete, TWEQ_COMPLETE) 258 259/* 260 * outstanding bio queue 261 */ 262static __inline void 263twe_initq_bio(struct twe_softc *sc) 264{ 265 TWE_BIO_QINIT(sc->twe_bioq); 266 TWEQ_INIT(sc, TWEQ_BIO); 267} 268 269static __inline void 270twe_enqueue_bio(struct twe_softc *sc, twe_bio *bp) 271{ 272 int s; 273 274 s = splbio(); 275 TWE_BIO_QINSERT(sc->twe_bioq, bp); 276 TWEQ_ADD(sc, TWEQ_BIO); 277 splx(s); 278} 279 280static __inline twe_bio * 281twe_dequeue_bio(struct twe_softc *sc) 282{ 283 int s; 284 twe_bio *bp; 285 286 s = splbio(); 287 if ((bp = TWE_BIO_QFIRST(sc->twe_bioq)) != NULL) { 288 TWE_BIO_QREMOVE(sc->twe_bioq, bp); 289 TWEQ_REMOVE(sc, TWEQ_BIO); 290 } 291 splx(s); 292 return(bp); 293}
|