Fix debug line and only check the media change if the io operation succeeds.
[AROS.git] / rom / devs / ahci / ahci_cam_aros.c
blob800879aca637dff386e30a4f9aa9fc6009795165
1 /*
2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
6 */
8 #include <aros/debug.h>
9 #include <aros/atomic.h>
11 #include <proto/exec.h>
12 #include <proto/expansion.h>
13 #include <proto/dos.h>
15 #include <dos/filehandler.h>
17 #include <devices/trackdisk.h>
18 #include <devices/scsidisk.h>
20 #include <scsi/commands.h>
21 #include <scsi/values.h>
23 #include "ahci.h"
24 #include "ahci_scsi.h"
25 #include "timer.h"
27 #include LC_LIBDEFS_FILE
30 * Execute a SCSI TEST UNIT READY every 250ms, to see
31 * if the medium has changed.
33 static void ahci_PortMonitor(struct Task *parent, struct Device *device, struct cam_sim *unit)
35 struct MsgPort *mp;
36 struct IORequest *tmr;
38 D(bug("%s %d: Monitor Start\n", ((struct Node *)device)->ln_Name, unit->sim_Unit));
39 AROS_ATOMIC_INC(unit->sim_UseCount);
40 Signal(parent, SIGBREAKF_CTRL_C);
42 tmr = ahci_OpenTimer();
43 if (!tmr)
44 return;
46 if ((mp = CreateMsgPort())) {
47 struct IORequest *io;
48 if ((io = CreateIORequest(mp, sizeof(struct IOStdReq)))) {
49 BOOL media_present = FALSE;
51 struct scsi_generic test_unit_ready = { .opcode = SCSI_TEST_UNIT_READY, };
52 struct scsi_sense_data sense = {};
53 struct SCSICmd scsi = {};
55 io->io_Device = device;
56 io->io_Unit = (struct Unit *)unit;
58 D(bug("%s %d: Monitoring\n", ((struct Node *)device)->ln_Name, unit->sim_Unit));
59 do {
60 /* Issue a dummy read and gather sense data as we wish to get the current sense and not the previous */
61 io->io_Command = HD_SCSICMD;
62 io->io_Flags = 0;
63 io->io_Error = 0;
64 IOStdReq(io)->io_Data = &scsi;
65 IOStdReq(io)->io_Length = sizeof(scsi);
66 IOStdReq(io)->io_Actual = 0;
67 scsi.scsi_Data = NULL;
68 scsi.scsi_Length = 0;
69 scsi.scsi_Command = (UBYTE *)&test_unit_ready;
70 scsi.scsi_CmdLength = sizeof(test_unit_ready);
71 scsi.scsi_Actual = 0;
72 scsi.scsi_Status = 0;
73 scsi.scsi_Flags = SCSIF_READ|SCSIF_AUTOSENSE|0x80;
74 scsi.scsi_SenseData = (UBYTE *)&sense;
75 scsi.scsi_SenseLength = sizeof(sense);
76 scsi.scsi_SenseActual = 0;
78 DoIO(io);
80 if((io->io_Error == 0)) {
81 if((scsi.scsi_Status != SCSI_GOOD)) {
82 if((sense.flags & SSD_KEY) == SSD_KEY_NOT_READY) {
83 /* Medium is not present and tray is either closed or open (when additional sense code is 0x3a) */
84 if(sense.add_sense_code == 0x3a) {
85 media_present = FALSE;
87 if(sense.add_sense_qual == 1) {
88 // medium not present - tray closed
90 if(sense.add_sense_qual == 2) {
91 // medium not present - tray open
97 } else {
98 /* When status returns GOOD, sense key is not applicable -> assume media to be present */
99 media_present = TRUE;
102 /* Presence of media has changed */
103 if((unit->sim_Flags |= SIMF_MediaPresent) != (media_present)) {
104 ObtainSemaphore(&unit->sim_Lock);
105 if (media_present) {
106 unit->sim_Flags |= SIMF_MediaPresent;
107 } else {
108 unit->sim_Flags &= ~SIMF_MediaPresent;
110 unit->sim_ChangeNum++;
111 ReleaseSemaphore(&unit->sim_Lock);
113 struct IORequest *msg;
115 D(bug("%s: Media change detected on ahci.device %d (media is %s)\n", __func__, unit->sim_Unit, media_present ? "present" : "not present"));
117 Forbid();
118 ForeachNode((struct Node *)&unit->sim_IOs, msg) {
119 D(bug("%s %d: io_Command = 0x%04x\n", ((struct Node *)device)->ln_Name, unit->sim_Unit, msg->io_Command));
120 if (msg->io_Command == TD_ADDCHANGEINT) {
121 D(bug("%s %d: Interrupt = 0x%p\n", ((struct Node *)device)->ln_Name, unit->sim_Unit, IOStdReq(msg)->io_Data));
122 Cause((struct Interrupt *)IOStdReq(msg)->io_Data);
125 Permit();
130 /* Wait 1s to the next scan */
131 } while ((ahci_WaitTO(tmr, 1, 0, SIGF_DOS) & SIGF_DOS) == 0);
133 DeleteIORequest(io);
135 DeleteMsgPort(mp);
137 AROS_ATOMIC_DEC(unit->sim_UseCount);
138 D(bug("%s %d: Monitor End\n", ((struct Node *)device)->ln_Name, unit->sim_Unit));
141 static int ahci_RegisterPort(struct ahci_port *ap)
143 struct AHCIBase *AHCIBase = ap->ap_sc->sc_dev->dev_AHCIBase;
144 struct cam_sim *unit;
145 char name[64];
147 unit = AllocPooled(AHCIBase->ahci_MemPool, sizeof(*unit));
148 if (!unit)
149 return ENOMEM;
151 ap->ap_sim = unit;
152 unit->sim_Port = ap;
153 unit->sim_Unit = ap->ap_sc->sc_dev->dev_HostID * 32 + ap->ap_num;
154 InitSemaphore(&unit->sim_Lock);
155 NEWLIST(&unit->sim_IOs);
157 AddTail((struct List *)&AHCIBase->ahci_Units, (struct Node *)unit);
159 /* Now that this device is in the unit list, start the disk change monitor */
160 snprintf(name, sizeof(name), "ahci.device %d [media]", unit->sim_Unit);
161 unit->sim_Monitor = NewCreateTask(TASKTAG_NAME, name,
162 TASKTAG_PC, ahci_PortMonitor,
163 TASKTAG_ARG1, FindTask(NULL),
164 TASKTAG_ARG2, AHCIBase,
165 TASKTAG_ARG3, unit,
166 TAG_END);
168 Wait(SIGBREAKF_CTRL_C);
170 return 0;
173 static int ahci_UnregisterPort(struct ahci_port *ap)
175 struct ahci_softc *sc = ap->ap_sc;
176 struct AHCIBase *AHCIBase;
177 struct cam_sim *unit = ap->ap_sim;
179 D(bug("ahci_UnregisterPort: %p\n", ap));
181 if (sc == NULL) {
182 D(bug("No softc?\n"));
183 return 0;
186 AHCIBase = sc->sc_dev->dev_AHCIBase;
188 /* Stop the monitor, and wait for IOs to drain,
189 * and users to CloseDevice() the unit.
191 if (unit->sim_Monitor)
192 Signal(unit->sim_Monitor, SIGF_DOS);
193 ObtainSemaphore(&unit->sim_Lock);
194 while (unit->sim_UseCount) {
195 ReleaseSemaphore(&unit->sim_Lock);
196 ahci_os_sleep(100);
197 ObtainSemaphore(&unit->sim_Lock);
199 ReleaseSemaphore(&unit->sim_Lock);
201 /* Remove from the unit list */
202 Forbid();
203 Remove((struct Node *)unit);
204 Permit();
206 FreePooled(AHCIBase->ahci_MemPool, unit, sizeof(*unit));
208 return 0;
211 /* Add a bootnode using expansion.library,
212 * but only when dos.library has not yet been initialized.
213 * This way, we get BootNodes if ahci.device is linked in,
214 * but don't if ahci.device is loaded after booting.
216 static BOOL ahci_RegisterVolume(struct ahci_port *ap, struct ata_port *at)
218 struct ExpansionBase *ExpansionBase;
219 BOOL dos_loaded;
220 struct DeviceNode *devnode;
221 TEXT dosdevname[4] = "HA0";
222 const ULONG DOS_ID = AROS_MAKE_ID('D','O','S','\001');
223 const ULONG CDROM_ID = AROS_MAKE_ID('C','D','V','D');
224 ULONG unit = device_get_unit(ap->ap_sc->sc_dev) * 32 + ap->ap_num;
226 D(bug("%s: ap = %p, at = %p, unit = %d\n", __func__, ap, at, ap->ap_sim ? ap->ap_sim->sim_Unit : -1));
228 /* See if dos.library has run */
229 Forbid();
230 dos_loaded = (FindName (&SysBase->LibList, "dos.library") != NULL);
231 Permit();
233 if (dos_loaded) {
234 D(bug("%s: refused to register as boot volume - dos.library already loaded\n", __func__));
235 return FALSE;
238 if (at == NULL || ap->ap_type == ATA_PORT_T_NONE)
239 return FALSE;
241 /* This should be dealt with using some sort of volume manager or such. */
242 switch (ap->ap_type)
244 case ATA_PORT_T_DISK:
245 break;
246 case ATA_PORT_T_ATAPI:
247 dosdevname[0] = 'C';
248 break;
249 default:
250 D(bug("[AHCI>>]:-ahci_RegisterVolume called on unknown devicetype\n"));
251 return FALSE;
254 ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",
255 40L);
257 if (ExpansionBase)
259 IPTR pp[4 + DE_BOOTBLOCKS + 1];
261 if (ap->ap_num < 10)
262 dosdevname[2] += ap->ap_num;
263 else
264 dosdevname[2] = 'A' + (ap->ap_num - 10);
266 pp[0] = (IPTR)dosdevname;
267 pp[1] = (IPTR)MOD_NAME_STRING;
268 pp[2] = unit;
269 pp[DE_TABLESIZE + 4] = DE_BOOTBLOCKS;
270 pp[DE_SIZEBLOCK + 4] = at->at_identify.sector_size;
271 pp[DE_NUMHEADS + 4] = at->at_identify.nheads;
272 pp[DE_SECSPERBLOCK + 4] = 1;
273 pp[DE_BLKSPERTRACK + 4] = at->at_identify.nsectors;
274 pp[DE_RESERVEDBLKS + 4] = 2;
275 pp[DE_LOWCYL + 4] = 0;
276 pp[DE_HIGHCYL + 4] = (ap->ap_type == ATA_PORT_T_DISK) ? (at->at_identify.ncyls-1) : 0;
277 pp[DE_NUMBUFFERS + 4] = 10;
278 pp[DE_BUFMEMTYPE + 4] = MEMF_PUBLIC;
279 pp[DE_MAXTRANSFER + 4] = 0x00200000;
280 pp[DE_MASK + 4] = ~3;
281 pp[DE_BOOTPRI + 4] = (ap->ap_type == ATA_PORT_T_DISK) ? 0 : 10;
282 pp[DE_DOSTYPE + 4] = (ap->ap_type == ATA_PORT_T_DISK) ? DOS_ID : CDROM_ID;
283 pp[DE_BAUD + 4] = 0;
284 pp[DE_CONTROL + 4] = 0;
285 pp[DE_BOOTBLOCKS + 4] = 2;
287 devnode = MakeDosNode(pp);
289 if (devnode) {
290 D(bug("[AHCI>>]:-ahci_RegisterVolume: '%s' C/H/S=%d/%d/%d, %s unit %d\n",
291 AROS_BSTR_ADDR(devnode->dn_Name), at->at_identify.ncyls, at->at_identify.nheads, at->at_identify.nsectors, MOD_NAME_STRING, unit));
292 AddBootNode(pp[DE_BOOTPRI + 4], 0, devnode, 0);
293 D(bug("[AHCI>>]:-ahci_RegisterVolume: done\n"));
294 return TRUE;
297 CloseLibrary((struct Library *)ExpansionBase);
300 return FALSE;
304 int ahci_cam_attach(struct ahci_port *ap)
306 int error;
308 D(bug("ahci_cam_attach: port %p\n", ap));
310 ahci_os_unlock_port(ap);
311 lockmgr(&ap->ap_sim_lock, LK_EXCLUSIVE);
312 error = ahci_RegisterPort(ap);
313 lockmgr(&ap->ap_sim_lock, LK_RELEASE);
314 ahci_os_lock_port(ap);
315 if (error) {
316 ahci_cam_detach(ap);
317 return (EINVAL);
319 ap->ap_flags |= AP_F_BUS_REGISTERED;
321 if (ap->ap_probe == ATA_PROBE_NEED_IDENT)
322 error = ahci_cam_probe(ap, NULL);
323 else
324 error = 0;
325 if (error) {
326 ahci_cam_detach(ap);
327 return (EIO);
330 ap->ap_flags |= AP_F_CAM_ATTACHED;
332 return 0;
335 void ahci_cam_detach(struct ahci_port *ap)
337 D(bug("ahci_cam_detach: port %p\n", ap));
339 lockmgr(&ap->ap_sim_lock, LK_EXCLUSIVE);
340 if (ap->ap_flags & AP_F_BUS_REGISTERED) {
341 ap->ap_flags &= ~AP_F_BUS_REGISTERED;
343 if (ap->ap_sim) {
344 ahci_UnregisterPort(ap);
346 lockmgr(&ap->ap_sim_lock, LK_RELEASE);
347 ap->ap_flags &= ~AP_F_CAM_ATTACHED;
351 * The state of the port has changed.
353 * If atx is NULL the physical port has changed state.
354 * If atx is non-NULL a particular target behind a PM has changed state.
356 * If found is -1 the target state must be queued to a non-interrupt context.
357 * (only works with at == NULL).
359 * If found is 0 the target was removed.
360 * If found is 1 the target was inserted.
362 void ahci_cam_changed(struct ahci_port *ap, struct ata_port *atx, int found)
364 D(bug("ahci_cam_changed: ap=%p, sim = %p, atx=%p, found=%d\n", ap, ap->ap_sim, atx, found));
366 if (ap->ap_sim) {
367 if (found == 0) {
368 ap->ap_sim->sim_Flags |= SIMF_OffLine;
369 } else {
370 ap->ap_sim->sim_Flags &= ~SIMF_OffLine;
374 /* Mark the port scan as completed */
375 ap->ap_flags |= AP_F_SCAN_COMPLETED;
378 static void ahci_strip_string(const char **basep, int *lenp)
380 const char *base = *basep;
381 int len = *lenp;
383 while (len && (*base == 0 || *base == ' ')) {
384 --len;
385 ++base;
387 while (len && (base[len-1] == 0 || base[len-1] == ' '))
388 --len;
389 *basep = base;
390 *lenp = len;
393 static u_int16_t bswap16(u_int16_t word)
395 return ((word << 8) & 0xff00) |
396 ((word >> 8) & 0x00ff);
400 * Fix byte ordering so buffers can be accessed as
401 * strings.
403 static void
404 ata_fix_identify(struct ata_identify *id)
406 u_int16_t *swap;
407 int i;
409 swap = (u_int16_t *)id->serial;
410 for (i = 0; i < sizeof(id->serial) / sizeof(u_int16_t); i++)
411 swap[i] = bswap16(swap[i]);
413 swap = (u_int16_t *)id->firmware;
414 for (i = 0; i < sizeof(id->firmware) / sizeof(u_int16_t); i++)
415 swap[i] = bswap16(swap[i]);
417 swap = (u_int16_t *)id->model;
418 for (i = 0; i < sizeof(id->model) / sizeof(u_int16_t); i++)
419 swap[i] = bswap16(swap[i]);
423 * Dummy done callback for xa.
425 static void ahci_ata_dummy_done(struct ata_xfer *xa)
430 * Setting the transfer mode is irrelevant for the SATA transport
431 * but some (atapi) devices seem to need it anyway. In addition
432 * if we are running through a SATA->PATA converter for some reason
433 * beyond my comprehension we might have to set the mode.
435 * We only support DMA modes for SATA attached devices, so don't bother
436 * with legacy modes.
438 static int
439 ahci_set_xfer(struct ahci_port *ap, struct ata_port *atx)
441 struct ata_port *at;
442 struct ata_xfer *xa;
443 u_int16_t mode;
444 u_int16_t mask;
446 at = atx ? atx : ap->ap_ata[0];
449 * Figure out the supported UDMA mode. Ignore other legacy modes.
451 mask = le16toh(at->at_identify.ultradma);
452 if ((mask & 0xFF) == 0 || mask == 0xFFFF)
453 return(0);
454 mask &= 0xFF;
455 mode = 0x4F;
456 while ((mask & 0x8000) == 0) {
457 mask <<= 1;
458 --mode;
462 * SATA atapi devices often still report a dma mode, even though
463 * it is irrelevant for SATA transport. It is also possible that
464 * we are running through a SATA->PATA converter and seeing the
465 * PATA dma mode.
467 * In this case the device may require a (dummy) SETXFER to be
468 * sent before it will work properly.
470 xa = ahci_ata_get_xfer(ap, atx);
471 xa->complete = ahci_ata_dummy_done;
472 xa->fis->command = ATA_C_SET_FEATURES;
473 xa->fis->features = ATA_SF_SETXFER;
474 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
475 xa->fis->sector_count = mode;
476 xa->flags = ATA_F_PIO | ATA_F_POLL;
477 xa->timeout = 1000;
478 xa->datalen = 0;
479 if (ahci_ata_cmd(xa) != ATA_S_COMPLETE) {
480 kprintf("%s: Unable to set dummy xfer mode \n",
481 ATANAME(ap, atx));
482 } else if (bootverbose) {
483 kprintf("%s: Set dummy xfer mode to %02x\n",
484 ATANAME(ap, atx), mode);
486 ahci_ata_put_xfer(xa);
487 return(0);
492 * DISK-specific probe after initial ident
494 static int
495 ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
497 struct ata_port *at;
498 struct ata_xfer *xa;
500 at = atx ? atx : ap->ap_ata[0];
503 * Set dummy xfer mode
505 ahci_set_xfer(ap, atx);
508 * Enable write cache if supported
510 * NOTE: "WD My Book" external disk devices have a very poor
511 * daughter board between the the ESATA and the HD. Sending
512 * any ATA_C_SET_FEATURES commands will break the hardware port
513 * with a fatal protocol error. However, this device also
514 * indicates that WRITECACHE is already on and READAHEAD is
515 * not supported so we avoid the issue.
517 if ((at->at_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) &&
518 (at->at_identify.features85 & ATA_IDENTIFY_WRITECACHE) == 0) {
519 xa = ahci_ata_get_xfer(ap, atx);
520 xa->complete = ahci_ata_dummy_done;
521 xa->fis->command = ATA_C_SET_FEATURES;
522 xa->fis->features = ATA_SF_WRITECACHE_EN;
523 /* xa->fis->features = ATA_SF_LOOKAHEAD_EN; */
524 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
525 xa->fis->device = 0;
526 xa->flags = ATA_F_PIO | ATA_F_POLL;
527 xa->timeout = 1000;
528 xa->datalen = 0;
529 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
530 at->at_features |= ATA_PORT_F_WCACHE;
531 else
532 kprintf("%s: Unable to enable write-caching\n",
533 ATANAME(ap, atx));
534 ahci_ata_put_xfer(xa);
538 * Enable readahead if supported
540 if ((at->at_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) &&
541 (at->at_identify.features85 & ATA_IDENTIFY_LOOKAHEAD) == 0) {
542 xa = ahci_ata_get_xfer(ap, atx);
543 xa->complete = ahci_ata_dummy_done;
544 xa->fis->command = ATA_C_SET_FEATURES;
545 xa->fis->features = ATA_SF_LOOKAHEAD_EN;
546 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
547 xa->fis->device = 0;
548 xa->flags = ATA_F_PIO | ATA_F_POLL;
549 xa->timeout = 1000;
550 xa->datalen = 0;
551 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
552 at->at_features |= ATA_PORT_F_RAHEAD;
553 else
554 kprintf("%s: Unable to enable read-ahead\n",
555 ATANAME(ap, atx));
556 ahci_ata_put_xfer(xa);
560 * FREEZE LOCK the device so malicious users can't lock it on us.
561 * As there is no harm in issuing this to devices that don't
562 * support the security feature set we just send it, and don't bother
563 * checking if the device sends a command abort to tell us it doesn't
564 * support it
566 if ((at->at_identify.cmdset82 & ATA_IDENTIFY_SECURITY) &&
567 (at->at_identify.securestatus & ATA_SECURE_FROZEN) == 0 &&
568 (AhciNoFeatures & (1 << ap->ap_num)) == 0) {
569 xa = ahci_ata_get_xfer(ap, atx);
570 xa->complete = ahci_ata_dummy_done;
571 xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
572 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
573 xa->flags = ATA_F_PIO | ATA_F_POLL;
574 xa->timeout = 1000;
575 xa->datalen = 0;
576 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
577 at->at_features |= ATA_PORT_F_FRZLCK;
578 else
579 kprintf("%s: Unable to set security freeze\n",
580 ATANAME(ap, atx));
581 ahci_ata_put_xfer(xa);
584 /* Fix up sector size, if the Word 106 is valid */
585 if ((at->at_identify.phys_sect_sz & 0xc000) == 0x4000) {
586 /* Physical sector size is longer than 256 16-bit words? */
587 if (at->at_identify.phys_sect_sz & (1 << 12)) {
588 ULONG logsize;
589 D(ULONG physize;)
590 logsize = at->at_identify.words_lsec[0];
591 logsize <<= 16;
592 logsize += at->at_identify.words_lsec[1];
593 D(physize = logsize >> (at->at_identify.phys_sect_sz & 3));
594 D(kprintf("%s: Logical sector size: %d bytes\n",
595 ATANAME(ap, atx), logsize * 2));
596 D(kprintf("%s: Physical sector size: %d bytes\n",
597 ATANAME(ap, atx), physize * 2));
598 at->at_identify.sector_size = logsize * 2;
599 } else {
600 D(kprintf("%s: Physical sector size == Logical sector size\n", ATANAME(ap, atx)));
601 at->at_identify.sector_size = 256 * 2;
603 } else {
604 kprintf("%s: ATA IDENTIFY: Invalid Word 106: 0x%04x\n", ATANAME(ap, atx), at->at_identify.phys_sect_sz);
605 at->at_identify.sector_size = 256 * 2;
607 D(kprintf("%s: Sector size: %d bytes\n", ATANAME(ap, atx), at->at_identify.sector_size));
609 #if 1 /* Temporary debugging... */
610 int i;
611 kprintf("%s: ATA IDENTIFY\n", ATANAME(ap, atx));
612 for (i = 0; i < 128; i++) {
613 if ((i%8) == 0) kprintf("%s %3d:", ATANAME(ap, atx), i);
614 kprintf(" %04x", ((uint16_t *)(&at->at_identify))[i]);
615 if ((i%8) == 7) kprintf("\n");
617 #endif
619 return (0);
623 * ATAPI-specific probe after initial ident
625 static int
626 ahci_cam_probe_atapi(struct ahci_port *ap, struct ata_port *atx)
628 ahci_set_xfer(ap, atx);
629 return(0);
634 * Once the AHCI port has been attached we need to probe for a device or
635 * devices on the port and setup various options.
637 * If at is NULL we are probing the direct-attached device on the port,
638 * which may or may not be a port multiplier.
641 ahci_cam_probe(struct ahci_port *ap, struct ata_port *atx)
643 struct ata_port *at;
644 struct ata_xfer *xa;
645 u_int64_t capacity;
646 u_int64_t capacity_bytes;
647 int model_len;
648 int firmware_len;
649 int serial_len;
650 int error;
651 int devncqdepth;
652 int i;
653 const char *model_id;
654 const char *firmware_id;
655 const char *serial_id;
656 const char *wcstr;
657 const char *rastr;
658 const char *scstr;
659 const char *type;
661 error = EIO;
664 * A NULL atx indicates a probe of the directly connected device.
665 * A non-NULL atx indicates a device connected via a port multiplier.
666 * We need to preserve atx for calls to ahci_ata_get_xfer().
668 * at is always non-NULL. For directly connected devices we supply
669 * an (at) pointing to target 0.
671 if (atx == NULL) {
672 at = ap->ap_ata[0]; /* direct attached - device 0 */
673 if (ap->ap_type == ATA_PORT_T_PM) {
674 kprintf("%s: Found Port Multiplier\n",
675 ATANAME(ap, atx));
676 return (0);
678 at->at_type = ap->ap_type;
679 } else {
680 at = atx;
681 if (atx->at_type == ATA_PORT_T_PM) {
682 kprintf("%s: Bogus device, reducing port count to %d\n",
683 ATANAME(ap, atx), atx->at_target);
684 if (ap->ap_pmcount > atx->at_target)
685 ap->ap_pmcount = atx->at_target;
686 goto err;
689 if (ap->ap_type == ATA_PORT_T_NONE)
690 goto err;
691 if (at->at_type == ATA_PORT_T_NONE)
692 goto err;
695 * Issue identify, saving the result
697 xa = ahci_ata_get_xfer(ap, atx);
698 xa->complete = ahci_ata_dummy_done;
699 xa->data = &at->at_identify;
700 xa->datalen = sizeof(at->at_identify);
701 xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
702 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
704 switch(at->at_type) {
705 case ATA_PORT_T_DISK:
706 xa->fis->command = ATA_C_IDENTIFY;
707 type = "DISK";
708 break;
709 case ATA_PORT_T_ATAPI:
710 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
711 xa->flags |= ATA_F_AUTOSENSE;
712 type = "ATAPI";
713 break;
714 default:
715 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
716 type = "UNKNOWN(ATAPI?)";
717 break;
719 xa->fis->features = 0;
720 xa->fis->device = 0;
721 xa->timeout = 1000;
723 if (ahci_ata_cmd(xa) != ATA_S_COMPLETE) {
724 kprintf("%s: Detected %s device but unable to IDENTIFY\n",
725 ATANAME(ap, atx), type);
726 ahci_ata_put_xfer(xa);
727 goto err;
729 ahci_ata_put_xfer(xa);
731 ata_fix_identify(&at->at_identify);
734 * Read capacity using SATA probe info.
736 if (le16toh(at->at_identify.cmdset83) & 0x0400) {
737 /* LBA48 feature set supported */
738 capacity = 0;
739 for (i = 3; i >= 0; --i) {
740 capacity <<= 16;
741 capacity +=
742 le16toh(at->at_identify.addrsecxt[i]);
744 } else {
745 capacity = le16toh(at->at_identify.addrsec[1]);
746 capacity <<= 16;
747 capacity += le16toh(at->at_identify.addrsec[0]);
749 if (capacity == 0)
750 capacity = 1024 * 1024 / 512;
751 at->at_capacity = capacity;
752 if (atx == NULL)
753 ap->ap_probe = ATA_PROBE_GOOD;
755 capacity_bytes = capacity * 512;
758 * Negotiate NCQ, throw away any ata_xfer's beyond the negotiated
759 * number of slots and limit the number of CAM ccb's to one less
760 * so we always have a slot available for recovery.
762 * NCQ is not used if ap_ncqdepth is 1 or the host controller does
763 * not support it, and in that case the driver can handle extra
764 * ccb's.
766 * NCQ is currently used only with direct-attached disks. It is
767 * not used with port multipliers or direct-attached ATAPI devices.
769 * Remember at least one extra CCB needs to be reserved for the
770 * error ccb.
772 if ((ap->ap_sc->sc_cap & AHCI_REG_CAP_SNCQ) &&
773 ap->ap_type == ATA_PORT_T_DISK &&
774 (le16toh(at->at_identify.satacap) & (1 << 8))) {
775 at->at_ncqdepth = (le16toh(at->at_identify.qdepth) & 0x1F) + 1;
776 devncqdepth = at->at_ncqdepth;
777 if (at->at_ncqdepth > ap->ap_sc->sc_ncmds)
778 at->at_ncqdepth = ap->ap_sc->sc_ncmds;
779 if (at->at_ncqdepth > 1) {
780 for (i = 0; i < ap->ap_sc->sc_ncmds; ++i) {
781 xa = ahci_ata_get_xfer(ap, atx);
782 if (xa->tag < at->at_ncqdepth) {
783 xa->state = ATA_S_COMPLETE;
784 ahci_ata_put_xfer(xa);
787 #if 0
788 if (at->at_ncqdepth >= ap->ap_sc->sc_ncmds) {
789 cam_sim_set_max_tags(ap->ap_sim,
790 at->at_ncqdepth - 1);
792 #endif
794 } else {
795 devncqdepth = 0;
798 model_len = sizeof(at->at_identify.model);
799 model_id = at->at_identify.model;
800 ahci_strip_string(&model_id, &model_len);
802 firmware_len = sizeof(at->at_identify.firmware);
803 firmware_id = at->at_identify.firmware;
804 ahci_strip_string(&firmware_id, &firmware_len);
806 serial_len = sizeof(at->at_identify.serial);
807 serial_id = at->at_identify.serial;
808 ahci_strip_string(&serial_id, &serial_len);
811 * Generate informatiive strings.
813 * NOTE: We do not automatically set write caching, lookahead,
814 * or the security state for ATAPI devices.
816 if (at->at_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) {
817 if (at->at_identify.features85 & ATA_IDENTIFY_WRITECACHE)
818 wcstr = "enabled";
819 else if (at->at_type == ATA_PORT_T_ATAPI)
820 wcstr = "disabled";
821 else
822 wcstr = "enabling";
823 } else {
824 wcstr = "notsupp";
827 if (at->at_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) {
828 if (at->at_identify.features85 & ATA_IDENTIFY_LOOKAHEAD)
829 rastr = "enabled";
830 else if (at->at_type == ATA_PORT_T_ATAPI)
831 rastr = "disabled";
832 else
833 rastr = "enabling";
834 } else {
835 rastr = "notsupp";
838 if (at->at_identify.cmdset82 & ATA_IDENTIFY_SECURITY) {
839 if (at->at_identify.securestatus & ATA_SECURE_FROZEN)
840 scstr = "frozen";
841 else if (at->at_type == ATA_PORT_T_ATAPI)
842 scstr = "unfrozen";
843 else if (AhciNoFeatures & (1 << ap->ap_num))
844 scstr = "<disabled>";
845 else
846 scstr = "freezing";
847 } else {
848 scstr = "notsupp";
851 kprintf("%s: Found %s \"%*.*s %*.*s\" serial=\"%*.*s\"\n"
852 "%s: tags=%d/%d satacap=%04x satafea=%04x NCQ=%s "
853 "capacity=%lld.%02dMB\n",
855 ATANAME(ap, atx),
856 type,
857 model_len, model_len, model_id,
858 firmware_len, firmware_len, firmware_id,
859 serial_len, serial_len, serial_id,
861 ATANAME(ap, atx),
862 devncqdepth, ap->ap_sc->sc_ncmds,
863 at->at_identify.satacap,
864 at->at_identify.satafsup,
865 (at->at_ncqdepth > 1 ? "YES" : "NO"),
866 (long long)capacity_bytes / (1024 * 1024),
867 (int)(capacity_bytes % (1024 * 1024)) * 100 / (1024 * 1024)
869 kprintf("%s: f85=%04x f86=%04x f87=%04x WC=%s RA=%s SEC=%s\n",
870 ATANAME(ap, atx),
871 at->at_identify.features85,
872 at->at_identify.features86,
873 at->at_identify.features87,
874 wcstr,
875 rastr,
876 scstr
880 * Additional type-specific probing
882 switch(at->at_type) {
883 case ATA_PORT_T_DISK:
884 error = ahci_cam_probe_disk(ap, atx);
885 break;
886 case ATA_PORT_T_ATAPI:
887 error = ahci_cam_probe_atapi(ap, atx);
888 break;
889 default:
890 error = EIO;
891 break;
893 err:
894 if (error) {
895 at->at_probe = ATA_PROBE_FAILED;
896 if (atx == NULL)
897 ap->ap_probe = at->at_probe;
898 } else {
899 at->at_probe = ATA_PROBE_GOOD;
900 if (atx == NULL)
901 ap->ap_probe = at->at_probe;
902 ahci_RegisterVolume(ap, at);
904 return (error);