atapi-cam.c revision 120315
1/*-
2 * Copyright (c) 2001-2003 Thomas Quinot <thomas@cuivre.fr.eu.org>
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
9 *    notice, this list of conditions and the following disclaimer,
10 *    without modification, immediately at the beginning of the file.
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 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/dev/ata/atapi-cam.c 120315 2003-09-21 08:53:05Z thomas $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/kernel.h>
36#include <sys/malloc.h>
37#include <sys/ata.h>
38#include <sys/taskqueue.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <machine/bus.h>
42
43#include <cam/cam.h>
44#include <cam/cam_ccb.h>
45#include <cam/cam_periph.h>
46#include <cam/cam_sim.h>
47#include <cam/cam_xpt_sim.h>
48#include <cam/cam_debug.h>
49#include <cam/scsi/scsi_all.h>
50
51#include <dev/ata/ata-all.h>
52
53/* hardware command descriptor block */
54struct atapi_hcb {
55    struct atapi_xpt_softc *softc;
56    int			unit;
57    int			bus;
58    int			target;
59    int			lun;
60    union ccb		*ccb;
61    int			flags;
62#define QUEUED		0x0001
63
64    char		*dxfer_alloc;
65    TAILQ_ENTRY(atapi_hcb) chain;
66};
67
68/* private data associated with an ATA bus */
69struct atapi_xpt_softc {
70    struct ata_channel	*ata_ch;
71    struct cam_path	*path;
72    struct cam_sim	*sim;
73    int			flags;
74#define BUS_REGISTERED		0x01
75#define RESOURCE_SHORTAGE	0x02
76
77    TAILQ_HEAD(,atapi_hcb) pending_hcbs;
78    LIST_ENTRY(atapi_xpt_softc) chain;
79};
80
81enum reinit_reason { BOOT_ATTACH, ATTACH, RESET };
82
83static struct mtx atapicam_softc_mtx;
84static LIST_HEAD(,atapi_xpt_softc) all_buses = LIST_HEAD_INITIALIZER(all_buses);
85
86/* CAM XPT methods */
87static void atapi_action(struct cam_sim *, union ccb *);
88static void atapi_poll(struct cam_sim *);
89static void atapi_async(void *, u_int32_t, struct cam_path *, void *);
90static void atapi_async1(void *, u_int32_t, struct cam_path *, void *);
91static void atapi_cb(struct ata_request *);
92
93/* internal functions */
94static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason);
95static void setup_dev(struct atapi_xpt_softc *, struct ata_device *);
96static void setup_async_cb(struct atapi_xpt_softc *, uint32_t);
97static void cam_rescan_callback(struct cam_periph *, union ccb *);
98static void cam_rescan(struct cam_sim *);
99static void free_hcb_and_ccb_done(struct atapi_hcb *, u_int32_t);
100static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *, int, int, union ccb *);
101static void free_hcb(struct atapi_hcb *hcb);
102static void free_softc(struct atapi_xpt_softc *scp);
103static struct atapi_xpt_softc *get_softc(struct ata_channel *ata_ch);
104static struct ata_device *get_ata_device(struct atapi_xpt_softc *scp, int id);
105
106static MALLOC_DEFINE(M_ATACAM, "ATA CAM transport", "ATA driver CAM-XPT layer");
107
108void
109atapi_cam_attach_bus(struct ata_channel *ata_ch)
110{
111    struct atapi_xpt_softc *scp = NULL;
112    struct cam_devq *devq = NULL;
113    struct cam_sim *sim = NULL;
114    struct cam_path *path = NULL;
115    int unit;
116
117    GIANT_REQUIRED;
118
119    if (mtx_initialized(&atapicam_softc_mtx) == 0)
120	mtx_init(&atapicam_softc_mtx, "ATAPI/CAM softc mutex", NULL, MTX_DEF);
121
122    mtx_lock(&atapicam_softc_mtx);
123
124    LIST_FOREACH(scp, &all_buses, chain) {
125	if (scp->ata_ch == ata_ch)
126	    break;
127    }
128    mtx_unlock(&atapicam_softc_mtx);
129
130    if (scp != NULL)
131	return;
132
133    if ((scp = malloc(sizeof(struct atapi_xpt_softc),
134		      M_ATACAM, M_NOWAIT | M_ZERO)) == NULL)
135	goto error;
136
137    scp->ata_ch = ata_ch;
138    TAILQ_INIT(&scp->pending_hcbs);
139    LIST_INSERT_HEAD(&all_buses, scp, chain);
140    unit = device_get_unit(ata_ch->dev);
141
142    if ((devq = cam_simq_alloc(16)) == NULL)
143	goto error;
144
145    if ((sim = cam_sim_alloc(atapi_action, atapi_poll, "ata",
146		 (void *)scp, unit, 1, 1, devq)) == NULL) {
147	cam_simq_free(devq);
148	goto error;
149    }
150    scp->sim = sim;
151
152    if (xpt_bus_register(sim, 0) != CAM_SUCCESS) {
153	goto error;
154    }
155    scp->flags |= BUS_REGISTERED;
156
157    if (xpt_create_path(&path, /*periph*/ NULL,
158		cam_sim_path(sim), CAM_TARGET_WILDCARD,
159		CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
160	goto error;
161    }
162    scp->path = path;
163
164    CAM_DEBUG(path, CAM_DEBUG_TRACE, ("Registered SIM for ata%d\n", unit));
165
166    setup_async_cb(scp, AC_LOST_DEVICE);
167    reinit_bus(scp, cold ? BOOT_ATTACH : ATTACH);
168    return;
169
170error:
171    free_softc(scp);
172}
173
174void
175atapi_cam_detach_bus(struct ata_channel *ata_ch)
176{
177    struct atapi_xpt_softc *scp = get_softc(ata_ch);
178
179    mtx_lock(&Giant);
180    free_softc(scp);
181    mtx_unlock(&Giant);
182}
183
184void
185atapi_cam_reinit_bus(struct ata_channel *ata_ch) {
186    struct atapi_xpt_softc *scp = get_softc(ata_ch);
187
188    /*
189     * scp might be null if the bus is being reinitialised during
190     * the boot-up sequence, before the ATAPI bus is registered.
191     */
192
193    if (scp != NULL) {
194	mtx_lock(&Giant);
195	reinit_bus(scp, RESET);
196	mtx_unlock(&Giant);
197    }
198}
199
200static void
201reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) {
202
203    GIANT_REQUIRED;
204
205    if (scp->ata_ch->devices & ATA_ATAPI_MASTER)
206	setup_dev(scp, &scp->ata_ch->device[MASTER]);
207    if (scp->ata_ch->devices & ATA_ATAPI_SLAVE)
208	setup_dev(scp, &scp->ata_ch->device[SLAVE]);
209
210    switch (reason) {
211	case BOOT_ATTACH:
212	    break;
213	case RESET:
214	    xpt_async(AC_BUS_RESET, scp->path, NULL);
215	    /*FALLTHROUGH*/
216	case ATTACH:
217	    cam_rescan(scp->sim);
218	    break;
219    }
220}
221
222static void
223setup_dev(struct atapi_xpt_softc *scp, struct ata_device *atp)
224{
225    if (atp->softc == NULL) {
226	ata_set_name(atp, "atapicam",
227		     2 * device_get_unit(atp->channel->dev) +
228		     (atp->unit == ATA_MASTER) ? 0 : 1);
229	atp->softc = (void *)scp;
230    }
231}
232
233static void
234setup_async_cb(struct atapi_xpt_softc *scp, uint32_t events)
235{
236    struct ccb_setasync csa;
237
238    GIANT_REQUIRED;
239
240    xpt_setup_ccb(&csa.ccb_h, scp->path, /*priority*/ 5);
241    csa.ccb_h.func_code = XPT_SASYNC_CB;
242    csa.event_enable = events;
243    csa.callback = &atapi_async;
244    csa.callback_arg = scp->sim;
245    xpt_action((union ccb *) &csa);
246}
247
248static void
249atapi_action(struct cam_sim *sim, union ccb *ccb)
250{
251    struct atapi_xpt_softc *softc = (struct atapi_xpt_softc*)cam_sim_softc(sim);
252    struct ccb_hdr *ccb_h = &ccb->ccb_h;
253    struct atapi_hcb *hcb = NULL;
254    struct ata_request *request = NULL;
255    int unit = cam_sim_unit(sim);
256    int bus = cam_sim_bus(sim);
257    int len;
258    char *buf;
259
260    switch (ccb_h->func_code) {
261    case XPT_PATH_INQ: {
262	struct ccb_pathinq *cpi = &ccb->cpi;
263
264	cpi->version_num = 1;
265	cpi->hba_inquiry = 0;
266	cpi->target_sprt = 0;
267	cpi->hba_misc = PIM_NO_6_BYTE;
268	cpi->hba_eng_cnt = 0;
269	bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags));
270	cpi->max_target = 1;
271	cpi->max_lun = 0;
272	cpi->async_flags = 0;
273	cpi->hpath_id = 0;
274	cpi->initiator_id = 7;
275	strncpy(cpi->sim_vid, "FreeBSD", sizeof(cpi->sim_vid));
276	strncpy(cpi->hba_vid, "ATAPI", sizeof(cpi->hba_vid));
277	strncpy(cpi->dev_name, cam_sim_name(sim), sizeof cpi->dev_name);
278	cpi->unit_number = cam_sim_unit(sim);
279	cpi->bus_id = cam_sim_bus(sim);
280	cpi->base_transfer_speed = 3300;
281
282	if (softc->ata_ch && ccb_h->target_id != CAM_TARGET_WILDCARD) {
283	    switch (softc->ata_ch->device[ccb_h->target_id].mode) {
284	    case ATA_PIO1:
285		cpi->base_transfer_speed = 5200;
286		break;
287	    case ATA_PIO2:
288		cpi->base_transfer_speed = 7000;
289		break;
290	    case ATA_PIO3:
291		cpi->base_transfer_speed = 11000;
292		break;
293	    case ATA_PIO4:
294	    case ATA_DMA:
295	    case ATA_WDMA2:
296		cpi->base_transfer_speed = 16000;
297		break;
298	    case ATA_UDMA2:
299		cpi->base_transfer_speed = 33000;
300		break;
301	    case ATA_UDMA4:
302		cpi->base_transfer_speed = 66000;
303		break;
304	    case ATA_UDMA5:
305		cpi->base_transfer_speed = 100000;
306		break;
307	    case ATA_UDMA6:
308		cpi->base_transfer_speed = 133000;
309		break;
310	    default:
311		break;
312	    }
313	}
314	ccb->ccb_h.status = CAM_REQ_CMP;
315	xpt_done(ccb);
316	return;
317    }
318
319    case XPT_RESET_DEV: {
320	int tid = ccb_h->target_id;
321	struct ata_device *dev = get_ata_device(softc, tid);
322
323	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("dev reset\n"));
324	ata_controlcmd(dev, ATA_ATAPI_RESET, 0, 0, 0);
325	ccb->ccb_h.status = CAM_REQ_CMP;
326	xpt_done(ccb);
327	return;
328    }
329
330    case XPT_RESET_BUS:
331	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("bus reset\n"));
332	ata_reinit(softc->ata_ch);
333	ccb->ccb_h.status = CAM_REQ_CMP;
334	xpt_done(ccb);
335	return;
336
337    case XPT_SET_TRAN_SETTINGS:
338	/* ignore these, we're not doing SCSI here */
339	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE,
340		  ("SET_TRAN_SETTINGS not supported\n"));
341	ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
342	xpt_done(ccb);
343	return;
344
345    case XPT_GET_TRAN_SETTINGS: {
346	struct ccb_trans_settings *cts = &ccb->cts;
347
348	/*
349	 * XXX The default CAM transport code is very SCSI-specific and
350	 * doesn't understand IDE speeds very well. Be silent about it
351	 * here and let it default to what is set in XPT_PATH_INQ
352	 */
353	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("GET_TRAN_SETTINGS\n"));
354	cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
355	cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
356	ccb->ccb_h.status = CAM_REQ_CMP;
357	xpt_done(ccb);
358	return;
359    }
360
361    case XPT_CALC_GEOMETRY: {
362	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("CALC_GEOMETRY\n"));
363	cam_calc_geometry(&ccb->ccg, /*extended*/1);
364	xpt_done(ccb);
365	return;
366    }
367
368    case XPT_SCSI_IO: {
369	struct ccb_scsiio *csio = &ccb->csio;
370	int tid = ccb_h->target_id, lid = ccb_h->target_lun;
371	struct ata_device *dev = get_ata_device(softc, tid);
372	int request_flags = ATA_R_QUIET | ATA_R_ATAPI;
373
374	CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, ("XPT_SCSI_IO\n"));
375
376	/* check that this request was not aborted already */
377	if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
378	    printf("XPT_SCSI_IO received but already in progress?\n");
379	    xpt_done(ccb);
380	    return;
381	}
382	if (dev == NULL) {
383	    CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
384		      ("SCSI IO received for invalid device\n"));
385	    goto action_invalid;
386	}
387	if (lid > 0) {
388	    CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
389		      ("SCSI IO received for invalid lun %d\n", lid));
390	    goto action_invalid;
391	}
392	if (csio->cdb_len > sizeof request->u.atapi.ccb) {
393	    CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
394		("CAM CCB too long for ATAPI"));
395	    goto action_invalid;
396	}
397	if ((ccb_h->flags & CAM_SCATTER_VALID)) {
398	    /* scatter-gather not supported */
399	    xpt_print_path(ccb_h->path);
400	    printf("ATAPI/CAM does not support scatter-gather yet!\n");
401	    goto action_invalid;
402	}
403
404	switch (ccb_h->flags & CAM_DIR_MASK) {
405	case CAM_DIR_IN:
406	     request_flags |= ATA_R_READ;
407	     break;
408	case CAM_DIR_OUT:
409	     request_flags |= ATA_R_WRITE;
410	     break;
411	case CAM_DIR_NONE:
412	     request_flags |= ATA_R_CONTROL;
413	     break;
414	default:
415	     ata_prtdev(dev, "unknown IO operation\n");
416	     goto action_invalid;
417	 }
418
419	if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) {
420	    printf("cannot allocate ATAPI/CAM hcb\n");
421	    goto action_oom;
422	}
423	if ((request = ata_alloc_request()) == NULL) {
424	    printf("cannot allocate ATAPI/CAM request\n");
425	    goto action_oom;
426	}
427
428	bcopy((ccb_h->flags & CAM_CDB_POINTER) ?
429	      csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes,
430	      request->u.atapi.ccb, csio->cdb_len);
431#ifdef CAMDEBUG
432	if (CAM_DEBUGGED(ccb_h->path, CAM_DEBUG_CDB)) {
433		char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
434
435		printf("atapi_action: hcb@%p: %s\n", hcb,
436		       scsi_cdb_string(request->u.atapi.ccb, cdb_str, sizeof(cdb_str)));
437	}
438#endif
439
440	len = csio->dxfer_len;
441	buf = csio->data_ptr;
442
443	/* some SCSI commands require special processing */
444	switch (request->u.atapi.ccb[0]) {
445	case INQUIRY: {
446	    /*
447	     * many ATAPI devices seem to report more than
448	     * SHORT_INQUIRY_LENGTH bytes of available INQUIRY
449	     * information, but respond with some incorrect condition
450	     * when actually asked for it, so we are going to pretend
451	     * that only SHORT_INQUIRY_LENGTH are expected, anyway.
452	     */
453	    struct scsi_inquiry *inq = (struct scsi_inquiry *) &request->u.atapi.ccb[0];
454
455	    if (inq->byte2 == 0 && inq->page_code == 0 &&
456		inq->length > SHORT_INQUIRY_LENGTH) {
457		bzero(buf, len);
458		len = inq->length = SHORT_INQUIRY_LENGTH;
459	    }
460	    break;
461	}
462	case READ_6:
463	    /* FALLTHROUGH */
464
465	case WRITE_6:
466	    CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
467		      ("Translating %s into _10 equivalent\n",
468		      (request->u.atapi.ccb[0] == READ_6) ? "READ_6" : "WRITE_6"));
469	    request->u.atapi.ccb[0] |= 0x20;
470	    request->u.atapi.ccb[9] = request->u.atapi.ccb[5];
471	    request->u.atapi.ccb[8] = request->u.atapi.ccb[4];
472	    request->u.atapi.ccb[7] = 0;
473	    request->u.atapi.ccb[6] = 0;
474	    request->u.atapi.ccb[5] = request->u.atapi.ccb[3];
475	    request->u.atapi.ccb[4] = request->u.atapi.ccb[2];
476	    request->u.atapi.ccb[3] = request->u.atapi.ccb[1] & 0x1f;
477	    request->u.atapi.ccb[2] = 0;
478	    request->u.atapi.ccb[1] = 0;
479	    break;
480	}
481
482	if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN && (len & 1)) {
483	    /* ATA always transfers an even number of bytes */
484	    if ((buf = hcb->dxfer_alloc
485                 = malloc(++len, M_ATACAM, M_NOWAIT | M_ZERO)) == NULL) {
486		printf("cannot allocate ATAPI/CAM buffer\n");
487		goto action_oom;
488	    }
489	}
490	request->device = dev;
491	request->driver = hcb;
492	request->data = buf;
493	request->bytecount = len;
494	request->transfersize = min(request->bytecount, 65534);
495	request->timeout = ccb_h->timeout;
496	request->retries = 2;
497	request->callback = &atapi_cb;
498	request->flags = request_flags;
499
500	TAILQ_INSERT_TAIL(&softc->pending_hcbs, hcb, chain);
501	hcb->flags |= QUEUED;
502	ccb_h->status |= CAM_SIM_QUEUED;
503
504	ata_queue_request(request);
505	return;
506    }
507
508    default:
509	CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE,
510		  ("unsupported function code 0x%02x\n", ccb_h->func_code));
511	goto action_invalid;
512    }
513
514    /* NOTREACHED */
515
516action_oom:
517    if (request != NULL)
518	ata_free_request(request);
519    if (hcb != NULL)
520	free_hcb(hcb);
521    xpt_print_path(ccb_h->path);
522    printf("out of memory, freezing queue.\n");
523    softc->flags |= RESOURCE_SHORTAGE;
524    xpt_freeze_simq(sim, /*count*/ 1);
525    ccb_h->status = CAM_REQUEUE_REQ;
526    xpt_done(ccb);
527    return;
528
529action_invalid:
530    ccb_h->status = CAM_REQ_INVALID;
531    xpt_done(ccb);
532    return;
533}
534
535static void
536atapi_poll(struct cam_sim *sim)
537{
538    /* do nothing - we do not actually service any interrupts */
539    printf("atapi_poll called!\n");
540}
541
542static void
543atapi_cb(struct ata_request *request)
544{
545    struct atapi_hcb *hcb = (struct atapi_hcb *) request->driver;
546    struct ccb_scsiio *csio = &hcb->ccb->csio;
547    int hcb_status = request->result;
548
549    mtx_lock(&Giant);
550
551#ifdef CAMDEBUG
552	if (CAM_DEBUGGED(csio->ccb_h.path, CAM_DEBUG_CDB)) {
553		printf("atapi_cb: hcb@%p status = %02x: (sk = %02x%s%s%s)\n",
554		       hcb, hcb_status, hcb_status >> 4,
555		       (hcb_status & 4) ? " ABRT" : "",
556		       (hcb_status & 2) ? " EOM" : "",
557		       (hcb_status & 1) ? " ILI" : "");
558		printf("    %s: cmd %02x\n",
559		    request->device->name, request->u.atapi.ccb[0]);
560	}
561#endif
562    if (hcb_status != 0) {
563	csio->scsi_status = SCSI_STATUS_CHECK_COND;
564#if 0
565	/*
566         * XXX Temporarily disable autosense, as this seems to cause
567	 * a missed ATA interrupt.
568	 */
569	if ((csio->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) {
570	    int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0,
571		sizeof(struct atapi_sense), 0, 0, 0, 0, 0, 0,
572		0, 0, 0, 0, 0 };
573
574	    if (ata_atapicmd(request->device, ccb, (caddr_t)&csio->sense_data,
575		sizeof(struct atapi_sense), ATA_R_READ, 30) == 0)
576	    {
577		csio->ccb_h.status |= CAM_AUTOSNS_VALID;
578	    }
579	}
580#endif
581	free_hcb_and_ccb_done(hcb, CAM_SCSI_STATUS_ERROR);
582    }
583    else {
584	if (((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) &&
585	    hcb->dxfer_alloc != NULL)
586	{
587	    bcopy(hcb->dxfer_alloc, csio->data_ptr, csio->dxfer_len);
588	}
589	csio->scsi_status = SCSI_STATUS_OK;
590	free_hcb_and_ccb_done(hcb, CAM_REQ_CMP);
591    }
592    mtx_unlock(&Giant);
593}
594
595static void
596free_hcb_and_ccb_done(struct atapi_hcb *hcb, u_int32_t status)
597{
598    struct atapi_xpt_softc *softc = hcb->softc;
599    union ccb *ccb = hcb->ccb;
600
601    GIANT_REQUIRED;
602
603    if (hcb != NULL) {
604	/* we're about to free a hcb, so the shortage has ended */
605	if (softc->flags & RESOURCE_SHORTAGE) {
606	    softc->flags &= ~RESOURCE_SHORTAGE;
607	    status |= CAM_RELEASE_SIMQ;
608	}
609	free_hcb(hcb);
610    }
611    ccb->ccb_h.status =
612	status | (ccb->ccb_h.status & ~(CAM_STATUS_MASK | CAM_SIM_QUEUED));
613    xpt_done(ccb);
614}
615
616static void
617atapi_async(void *callback_arg, u_int32_t code,
618	    struct cam_path *path, void *arg)
619{
620    mtx_lock(&Giant);
621    atapi_async1(callback_arg, code, path, arg);
622    mtx_unlock(&Giant);
623}
624
625static void
626atapi_async1(void *callback_arg, u_int32_t code,
627	     struct cam_path* path, void *arg)
628{
629    struct atapi_xpt_softc *softc;
630    struct cam_sim *sim;
631    int targ;
632
633    GIANT_REQUIRED;
634
635    sim = (struct cam_sim *) callback_arg;
636    softc = (struct atapi_xpt_softc *) cam_sim_softc(sim);
637    switch (code) {
638    case AC_LOST_DEVICE:
639	targ = xpt_path_target_id(path);
640	xpt_print_path(path);
641	if (targ == -1)
642		printf("Lost host adapter\n");
643	else
644		printf("Lost target %d???\n", targ);
645	break;
646
647    default:
648	break;
649    }
650}
651
652static void
653cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
654{
655	if (ccb->ccb_h.status != CAM_REQ_CMP) {
656	    CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
657		      ("Rescan failed, 0x%04x\n", ccb->ccb_h.status));
658	} else {
659	    CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
660		      ("Rescan succeeded\n"));
661	}
662	xpt_free_path(ccb->ccb_h.path);
663	free(ccb, M_ATACAM);
664}
665
666static void
667cam_rescan(struct cam_sim *sim)
668{
669    struct cam_path *path;
670    union ccb *ccb = malloc(sizeof(union ccb), M_ATACAM, M_WAITOK | M_ZERO);
671
672    if (xpt_create_path(&path, xpt_periph, cam_sim_path(sim),
673			CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
674	return;
675
676    CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("Rescanning ATAPI bus.\n"));
677    xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
678    ccb->ccb_h.func_code = XPT_SCAN_BUS;
679    ccb->ccb_h.cbfcnp = cam_rescan_callback;
680    ccb->crcn.flags = CAM_FLAG_NONE;
681    xpt_action(ccb);
682    /* scan is in progress now */
683}
684
685static struct atapi_hcb *
686allocate_hcb(struct atapi_xpt_softc *softc, int unit, int bus, union ccb *ccb)
687{
688    struct atapi_hcb *hcb = (struct atapi_hcb *)
689    malloc(sizeof(struct atapi_hcb), M_ATACAM, M_NOWAIT | M_ZERO);
690
691    if (hcb != NULL) {
692	hcb->softc = softc;
693	hcb->unit = unit;
694	hcb->bus = bus;
695	hcb->ccb = ccb;
696    }
697    return hcb;
698}
699
700static void
701free_hcb(struct atapi_hcb *hcb)
702{
703    if ((hcb->flags & QUEUED) != 0)
704	TAILQ_REMOVE(&hcb->softc->pending_hcbs, hcb, chain);
705    if (hcb->dxfer_alloc != NULL)
706	free(hcb->dxfer_alloc, M_ATACAM);
707    free(hcb, M_ATACAM);
708}
709
710static void
711free_softc(struct atapi_xpt_softc *scp)
712{
713    struct atapi_hcb *hcb;
714
715    GIANT_REQUIRED;
716
717    if (scp != NULL) {
718	TAILQ_FOREACH(hcb, &scp->pending_hcbs, chain) {
719	    free_hcb_and_ccb_done(hcb, CAM_UNREC_HBA_ERROR);
720	}
721	if (scp->path != NULL) {
722	    setup_async_cb(scp, 0);
723	    xpt_free_path(scp->path);
724	}
725	if ((scp->flags & BUS_REGISTERED) != 0) {
726	    if (xpt_bus_deregister(cam_sim_path(scp->sim)) == CAM_REQ_CMP)
727		scp->flags &= ~BUS_REGISTERED;
728	}
729	if (scp->sim != NULL) {
730	    if ((scp->flags & BUS_REGISTERED) == 0)
731		cam_sim_free(scp->sim, /*free_devq*/TRUE);
732	    else
733		printf("Can't free %s SIM (still registered)\n",
734		       cam_sim_name(scp->sim));
735	}
736	LIST_REMOVE(scp, chain);
737	free(scp, M_ATACAM);
738    }
739}
740
741static struct atapi_xpt_softc *
742get_softc(struct ata_channel *ata_ch) {
743    struct atapi_xpt_softc *scp = NULL;
744
745    mtx_lock(&atapicam_softc_mtx);
746    LIST_FOREACH(scp, &all_buses, chain) {
747	if (scp->ata_ch == ata_ch)
748	    break;
749    }
750    mtx_unlock(&atapicam_softc_mtx);
751    return scp;
752}
753
754static struct ata_device *
755get_ata_device(struct atapi_xpt_softc *scp, int id)
756{
757    int role = ATA_ATAPI_MASTER;
758
759    switch (id) {
760    case 1:
761	role = ATA_ATAPI_SLAVE;
762	/* FALLTHROUGH */
763
764    case 0:
765	if (scp->ata_ch->devices & role)
766	    return &scp->ata_ch->device[id];
767	/* FALLTHROUGH */
768
769    default:
770	return NULL;
771    }
772}
773