intuition.library: remove not needed include
[AROS.git] / rom / devs / ahci / ahci_cam_aros.c
blobc0861327aea9273ed9f04f40c5a4393d90276622
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 BOOL is_present;
62 io->io_Command = HD_SCSICMD;
63 io->io_Flags = 0;
64 io->io_Error = 0;
65 IOStdReq(io)->io_Data = &scsi;
66 IOStdReq(io)->io_Length = sizeof(scsi);
67 IOStdReq(io)->io_Actual = 0;
68 scsi.scsi_Command = (UBYTE *)&test_unit_ready;
69 scsi.scsi_CmdLength = sizeof(test_unit_ready);
70 scsi.scsi_Actual = 0;
71 scsi.scsi_Status = 0;
72 scsi.scsi_Flags = SCSIF_AUTOSENSE;
73 scsi.scsi_SenseData = (UBYTE *)&sense;
74 scsi.scsi_SenseLength = sizeof(sense);
75 scsi.scsi_SenseActual = 0;
77 DoIO(io);
79 is_present = (io->io_Error == 0) && (scsi.scsi_Status == SCSI_GOOD);
80 // TODO: Check sense for additional information
82 ObtainSemaphore(&unit->sim_Lock);
83 if (is_present)
84 unit->sim_Flags |= SIMF_MediaPresent;
85 else
86 unit->sim_Flags &= ~SIMF_MediaPresent;
87 if (is_present != media_present)
88 unit->sim_ChangeNum++;
89 ReleaseSemaphore(&unit->sim_Lock);
91 if (is_present != media_present) {
92 struct IORequest *msg;
94 D(bug("%s: Media change detected on ahci.device %d (%s => %s)\n", __func__, unit->sim_Unit, media_present ? "TRUE" : "FALSE", is_present ? "TRUE" : "FALSE"));
96 Forbid();
97 ForeachNode((struct Node *)&unit->sim_IOs, msg) {
98 D(bug("%s %d: io_Command = 0x%04x\n", ((struct Node *)device)->ln_Name, unit->sim_Unit, msg->io_Command));
99 if (msg->io_Command == TD_ADDCHANGEINT) {
100 D(bug("%s %d: Interrupt = 0x%p\n", ((struct Node *)device)->ln_Name, unit->sim_Unit, IOStdReq(msg)->io_Data));
101 Cause((struct Interrupt *)IOStdReq(msg)->io_Data);
104 Permit();
106 media_present = is_present;
108 /* Wait 1s to the next scan */
109 } while ((ahci_WaitTO(tmr, 1, 0, SIGF_DOS) & SIGF_DOS) == 0);
111 DeleteIORequest(io);
113 DeleteMsgPort(mp);
115 AROS_ATOMIC_DEC(unit->sim_UseCount);
116 D(bug("%s %d: Monitor End\n", ((struct Node *)device)->ln_Name, unit->sim_Unit));
119 static int ahci_RegisterPort(struct ahci_port *ap)
121 struct AHCIBase *AHCIBase = ap->ap_sc->sc_dev->dev_AHCIBase;
122 struct cam_sim *unit;
123 char name[64];
125 unit = AllocPooled(AHCIBase->ahci_MemPool, sizeof(*unit));
126 if (!unit)
127 return ENOMEM;
129 ap->ap_sim = unit;
130 unit->sim_Port = ap;
131 unit->sim_Unit = ap->ap_sc->sc_dev->dev_HostID * 32 + ap->ap_num;
132 InitSemaphore(&unit->sim_Lock);
133 NEWLIST(&unit->sim_IOs);
135 AddTail((struct List *)&AHCIBase->ahci_Units, (struct Node *)unit);
137 /* Now that this device is in the unit list, start the disk change monitor */
138 snprintf(name, sizeof(name), "ahci.device %d [media]", unit->sim_Unit);
139 unit->sim_Monitor = NewCreateTask(TASKTAG_NAME, name,
140 TASKTAG_PC, ahci_PortMonitor,
141 TASKTAG_ARG1, FindTask(NULL),
142 TASKTAG_ARG2, AHCIBase,
143 TASKTAG_ARG3, unit,
144 TAG_END);
146 Wait(SIGBREAKF_CTRL_C);
148 return 0;
151 static int ahci_UnregisterPort(struct ahci_port *ap)
153 struct ahci_softc *sc = ap->ap_sc;
154 struct AHCIBase *AHCIBase;
155 struct cam_sim *unit = ap->ap_sim;
157 D(bug("ahci_UnregisterPort: %p\n", ap));
159 if (sc == NULL) {
160 D(bug("No softc?\n"));
161 return 0;
164 AHCIBase = sc->sc_dev->dev_AHCIBase;
166 /* Stop the monitor, and wait for IOs to drain,
167 * and users to CloseDevice() the unit.
169 if (unit->sim_Monitor)
170 Signal(unit->sim_Monitor, SIGF_DOS);
171 ObtainSemaphore(&unit->sim_Lock);
172 while (unit->sim_UseCount) {
173 ReleaseSemaphore(&unit->sim_Lock);
174 ahci_os_sleep(100);
175 ObtainSemaphore(&unit->sim_Lock);
177 ReleaseSemaphore(&unit->sim_Lock);
179 /* Remove from the unit list */
180 Forbid();
181 Remove((struct Node *)unit);
182 Permit();
184 FreePooled(AHCIBase->ahci_MemPool, unit, sizeof(*unit));
186 return 0;
189 /* Add a bootnode using expansion.library,
190 * but only when dos.library has not yet been initialized.
191 * This way, we get BootNodes if ahci.device is linked in,
192 * but don't if ahci.device is loaded after booting.
194 static BOOL ahci_RegisterVolume(struct ahci_port *ap, struct ata_port *at)
196 struct ExpansionBase *ExpansionBase;
197 BOOL dos_loaded;
198 struct DeviceNode *devnode;
199 TEXT dosdevname[4] = "HA0";
200 const ULONG DOS_ID = AROS_MAKE_ID('D','O','S','\001');
201 const ULONG CDROM_ID = AROS_MAKE_ID('C','D','V','D');
202 ULONG unit = device_get_unit(ap->ap_sc->sc_dev) * 32 + ap->ap_num;
204 D(bug("%s: ap = %p, at = %p, unit = %d\n", __func__, ap, at, ap->ap_sim ? ap->ap_sim->sim_Unit : -1));
206 /* See if dos.library has run */
207 Forbid();
208 dos_loaded = (FindName (&SysBase->LibList, "dos.library") != NULL);
209 Permit();
211 if (dos_loaded) {
212 D(bug("%s: refused to register as boot volume - dos.library already loaded\n", __func__));
213 return FALSE;
216 if (at == NULL || ap->ap_type == ATA_PORT_T_NONE)
217 return FALSE;
219 /* This should be dealt with using some sort of volume manager or such. */
220 switch (ap->ap_type)
222 case ATA_PORT_T_DISK:
223 break;
224 case ATA_PORT_T_ATAPI:
225 dosdevname[0] = 'C';
226 break;
227 default:
228 D(bug("[AHCI>>]:-ahci_RegisterVolume called on unknown devicetype\n"));
229 return FALSE;
232 ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",
233 40L);
235 if (ExpansionBase)
237 IPTR pp[4 + DE_BOOTBLOCKS + 1];
239 if (ap->ap_num < 10)
240 dosdevname[2] += ap->ap_num;
241 else
242 dosdevname[2] = 'A' + (ap->ap_num - 10);
244 pp[0] = (IPTR)dosdevname;
245 pp[1] = (IPTR)MOD_NAME_STRING;
246 pp[2] = unit;
247 pp[DE_TABLESIZE + 4] = DE_BOOTBLOCKS;
248 pp[DE_SIZEBLOCK + 4] = at->at_identify.sector_size;
249 pp[DE_NUMHEADS + 4] = at->at_identify.nheads;
250 pp[DE_SECSPERBLOCK + 4] = 1;
251 pp[DE_BLKSPERTRACK + 4] = at->at_identify.nsectors;
252 pp[DE_RESERVEDBLKS + 4] = 2;
253 pp[DE_LOWCYL + 4] = 0;
254 pp[DE_HIGHCYL + 4] = (ap->ap_type == ATA_PORT_T_DISK) ? (at->at_identify.ncyls-1) : 0;
255 pp[DE_NUMBUFFERS + 4] = 10;
256 pp[DE_BUFMEMTYPE + 4] = MEMF_PUBLIC;
257 pp[DE_MAXTRANSFER + 4] = 0x00200000;
258 pp[DE_MASK + 4] = ~3;
259 pp[DE_BOOTPRI + 4] = (ap->ap_type == ATA_PORT_T_DISK) ? 0 : 10;
260 pp[DE_DOSTYPE + 4] = (ap->ap_type == ATA_PORT_T_DISK) ? DOS_ID : CDROM_ID;
261 pp[DE_BAUD + 4] = 0;
262 pp[DE_CONTROL + 4] = 0;
263 pp[DE_BOOTBLOCKS + 4] = 2;
265 devnode = MakeDosNode(pp);
267 if (devnode) {
268 D(bug("[AHCI>>]:-ahci_RegisterVolume: '%s' C/H/S=%d/%d/%d, %s unit %d\n",
269 AROS_BSTR_ADDR(devnode->dn_Name), at->at_identify.ncyls, at->at_identify.nheads, at->at_identify.nsectors, MOD_NAME_STRING, unit));
270 AddBootNode(pp[DE_BOOTPRI + 4], 0, devnode, 0);
271 D(bug("[AHCI>>]:-ahci_RegisterVolume: done\n"));
272 return TRUE;
275 CloseLibrary((struct Library *)ExpansionBase);
278 return FALSE;
282 int ahci_cam_attach(struct ahci_port *ap)
284 int error;
286 D(bug("ahci_cam_attach: port %p\n", ap));
288 ahci_os_unlock_port(ap);
289 lockmgr(&ap->ap_sim_lock, LK_EXCLUSIVE);
290 error = ahci_RegisterPort(ap);
291 lockmgr(&ap->ap_sim_lock, LK_RELEASE);
292 ahci_os_lock_port(ap);
293 if (error) {
294 ahci_cam_detach(ap);
295 return (EINVAL);
297 ap->ap_flags |= AP_F_BUS_REGISTERED;
299 if (ap->ap_probe == ATA_PROBE_NEED_IDENT)
300 error = ahci_cam_probe(ap, NULL);
301 else
302 error = 0;
303 if (error) {
304 ahci_cam_detach(ap);
305 return (EIO);
308 ap->ap_flags |= AP_F_CAM_ATTACHED;
310 return 0;
313 void ahci_cam_detach(struct ahci_port *ap)
315 D(bug("ahci_cam_detach: port %p\n", ap));
317 lockmgr(&ap->ap_sim_lock, LK_EXCLUSIVE);
318 if (ap->ap_flags & AP_F_BUS_REGISTERED) {
319 ap->ap_flags &= ~AP_F_BUS_REGISTERED;
321 if (ap->ap_sim) {
322 ahci_UnregisterPort(ap);
324 lockmgr(&ap->ap_sim_lock, LK_RELEASE);
325 ap->ap_flags &= ~AP_F_CAM_ATTACHED;
329 * The state of the port has changed.
331 * If atx is NULL the physical port has changed state.
332 * If atx is non-NULL a particular target behind a PM has changed state.
334 * If found is -1 the target state must be queued to a non-interrupt context.
335 * (only works with at == NULL).
337 * If found is 0 the target was removed.
338 * If found is 1 the target was inserted.
340 void ahci_cam_changed(struct ahci_port *ap, struct ata_port *atx, int found)
342 D(bug("ahci_cam_changed: ap=%p, sim = %p, atx=%p, found=%d\n", ap, ap->ap_sim, atx, found));
344 if (ap->ap_sim) {
345 if (found == 0) {
346 ap->ap_sim->sim_Flags |= SIMF_OffLine;
347 } else {
348 ap->ap_sim->sim_Flags &= ~SIMF_OffLine;
352 /* Mark the port scan as completed */
353 ap->ap_flags |= AP_F_SCAN_COMPLETED;
356 static void ahci_strip_string(const char **basep, int *lenp)
358 const char *base = *basep;
359 int len = *lenp;
361 while (len && (*base == 0 || *base == ' ')) {
362 --len;
363 ++base;
365 while (len && (base[len-1] == 0 || base[len-1] == ' '))
366 --len;
367 *basep = base;
368 *lenp = len;
371 static u_int16_t bswap16(u_int16_t word)
373 return ((word << 8) & 0xff00) |
374 ((word >> 8) & 0x00ff);
378 * Fix byte ordering so buffers can be accessed as
379 * strings.
381 static void
382 ata_fix_identify(struct ata_identify *id)
384 u_int16_t *swap;
385 int i;
387 swap = (u_int16_t *)id->serial;
388 for (i = 0; i < sizeof(id->serial) / sizeof(u_int16_t); i++)
389 swap[i] = bswap16(swap[i]);
391 swap = (u_int16_t *)id->firmware;
392 for (i = 0; i < sizeof(id->firmware) / sizeof(u_int16_t); i++)
393 swap[i] = bswap16(swap[i]);
395 swap = (u_int16_t *)id->model;
396 for (i = 0; i < sizeof(id->model) / sizeof(u_int16_t); i++)
397 swap[i] = bswap16(swap[i]);
401 * Dummy done callback for xa.
403 static void ahci_ata_dummy_done(struct ata_xfer *xa)
408 * Setting the transfer mode is irrelevant for the SATA transport
409 * but some (atapi) devices seem to need it anyway. In addition
410 * if we are running through a SATA->PATA converter for some reason
411 * beyond my comprehension we might have to set the mode.
413 * We only support DMA modes for SATA attached devices, so don't bother
414 * with legacy modes.
416 static int
417 ahci_set_xfer(struct ahci_port *ap, struct ata_port *atx)
419 struct ata_port *at;
420 struct ata_xfer *xa;
421 u_int16_t mode;
422 u_int16_t mask;
424 at = atx ? atx : ap->ap_ata[0];
427 * Figure out the supported UDMA mode. Ignore other legacy modes.
429 mask = le16toh(at->at_identify.ultradma);
430 if ((mask & 0xFF) == 0 || mask == 0xFFFF)
431 return(0);
432 mask &= 0xFF;
433 mode = 0x4F;
434 while ((mask & 0x8000) == 0) {
435 mask <<= 1;
436 --mode;
440 * SATA atapi devices often still report a dma mode, even though
441 * it is irrelevant for SATA transport. It is also possible that
442 * we are running through a SATA->PATA converter and seeing the
443 * PATA dma mode.
445 * In this case the device may require a (dummy) SETXFER to be
446 * sent before it will work properly.
448 xa = ahci_ata_get_xfer(ap, atx);
449 xa->complete = ahci_ata_dummy_done;
450 xa->fis->command = ATA_C_SET_FEATURES;
451 xa->fis->features = ATA_SF_SETXFER;
452 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
453 xa->fis->sector_count = mode;
454 xa->flags = ATA_F_PIO | ATA_F_POLL;
455 xa->timeout = 1000;
456 xa->datalen = 0;
457 if (ahci_ata_cmd(xa) != ATA_S_COMPLETE) {
458 kprintf("%s: Unable to set dummy xfer mode \n",
459 ATANAME(ap, atx));
460 } else if (bootverbose) {
461 kprintf("%s: Set dummy xfer mode to %02x\n",
462 ATANAME(ap, atx), mode);
464 ahci_ata_put_xfer(xa);
465 return(0);
470 * DISK-specific probe after initial ident
472 static int
473 ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
475 struct ata_port *at;
476 struct ata_xfer *xa;
478 at = atx ? atx : ap->ap_ata[0];
481 * Set dummy xfer mode
483 ahci_set_xfer(ap, atx);
486 * Enable write cache if supported
488 * NOTE: "WD My Book" external disk devices have a very poor
489 * daughter board between the the ESATA and the HD. Sending
490 * any ATA_C_SET_FEATURES commands will break the hardware port
491 * with a fatal protocol error. However, this device also
492 * indicates that WRITECACHE is already on and READAHEAD is
493 * not supported so we avoid the issue.
495 if ((at->at_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) &&
496 (at->at_identify.features85 & ATA_IDENTIFY_WRITECACHE) == 0) {
497 xa = ahci_ata_get_xfer(ap, atx);
498 xa->complete = ahci_ata_dummy_done;
499 xa->fis->command = ATA_C_SET_FEATURES;
500 xa->fis->features = ATA_SF_WRITECACHE_EN;
501 /* xa->fis->features = ATA_SF_LOOKAHEAD_EN; */
502 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
503 xa->fis->device = 0;
504 xa->flags = ATA_F_PIO | ATA_F_POLL;
505 xa->timeout = 1000;
506 xa->datalen = 0;
507 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
508 at->at_features |= ATA_PORT_F_WCACHE;
509 else
510 kprintf("%s: Unable to enable write-caching\n",
511 ATANAME(ap, atx));
512 ahci_ata_put_xfer(xa);
516 * Enable readahead if supported
518 if ((at->at_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) &&
519 (at->at_identify.features85 & ATA_IDENTIFY_LOOKAHEAD) == 0) {
520 xa = ahci_ata_get_xfer(ap, atx);
521 xa->complete = ahci_ata_dummy_done;
522 xa->fis->command = ATA_C_SET_FEATURES;
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_RAHEAD;
531 else
532 kprintf("%s: Unable to enable read-ahead\n",
533 ATANAME(ap, atx));
534 ahci_ata_put_xfer(xa);
538 * FREEZE LOCK the device so malicious users can't lock it on us.
539 * As there is no harm in issuing this to devices that don't
540 * support the security feature set we just send it, and don't bother
541 * checking if the device sends a command abort to tell us it doesn't
542 * support it
544 if ((at->at_identify.cmdset82 & ATA_IDENTIFY_SECURITY) &&
545 (at->at_identify.securestatus & ATA_SECURE_FROZEN) == 0 &&
546 (AhciNoFeatures & (1 << ap->ap_num)) == 0) {
547 xa = ahci_ata_get_xfer(ap, atx);
548 xa->complete = ahci_ata_dummy_done;
549 xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
550 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
551 xa->flags = ATA_F_PIO | ATA_F_POLL;
552 xa->timeout = 1000;
553 xa->datalen = 0;
554 if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
555 at->at_features |= ATA_PORT_F_FRZLCK;
556 else
557 kprintf("%s: Unable to set security freeze\n",
558 ATANAME(ap, atx));
559 ahci_ata_put_xfer(xa);
562 /* Fix up sector size, if the Word 106 is valid */
563 if ((at->at_identify.phys_sect_sz & 0xc000) == 0x4000) {
564 /* Physical sector size is longer than 256 16-bit words? */
565 if (at->at_identify.phys_sect_sz & (1 << 12)) {
566 ULONG logsize;
567 D(ULONG physize;)
568 logsize = at->at_identify.words_lsec[0];
569 logsize <<= 16;
570 logsize += at->at_identify.words_lsec[1];
571 D(physize = logsize >> (at->at_identify.phys_sect_sz & 3));
572 D(kprintf("%s: Logical sector size: %d bytes\n",
573 ATANAME(ap, atx), logsize * 2));
574 D(kprintf("%s: Physical sector size: %d bytes\n",
575 ATANAME(ap, atx), physize * 2));
576 at->at_identify.sector_size = logsize * 2;
577 } else {
578 D(kprintf("%s: Physical sector size == Logical sector size\n", ATANAME(ap, atx)));
579 at->at_identify.sector_size = 256 * 2;
581 } else {
582 kprintf("%s: ATA IDENTIFY: Invalid Word 106: 0x%04x\n", ATANAME(ap, atx), at->at_identify.phys_sect_sz);
583 at->at_identify.sector_size = 256 * 2;
585 D(kprintf("%s: Sector size: %d bytes\n", ATANAME(ap, atx), at->at_identify.sector_size));
587 #if 1 /* Temporary debugging... */
588 int i;
589 kprintf("%s: ATA IDENTIFY\n", ATANAME(ap, atx));
590 for (i = 0; i < 128; i++) {
591 if ((i%8) == 0) kprintf("%s %3d:", ATANAME(ap, atx), i);
592 kprintf(" %04x", ((uint16_t *)(&at->at_identify))[i]);
593 if ((i%8) == 7) kprintf("\n");
595 #endif
597 return (0);
601 * ATAPI-specific probe after initial ident
603 static int
604 ahci_cam_probe_atapi(struct ahci_port *ap, struct ata_port *atx)
606 ahci_set_xfer(ap, atx);
607 return(0);
612 * Once the AHCI port has been attached we need to probe for a device or
613 * devices on the port and setup various options.
615 * If at is NULL we are probing the direct-attached device on the port,
616 * which may or may not be a port multiplier.
619 ahci_cam_probe(struct ahci_port *ap, struct ata_port *atx)
621 struct ata_port *at;
622 struct ata_xfer *xa;
623 u_int64_t capacity;
624 u_int64_t capacity_bytes;
625 int model_len;
626 int firmware_len;
627 int serial_len;
628 int error;
629 int devncqdepth;
630 int i;
631 const char *model_id;
632 const char *firmware_id;
633 const char *serial_id;
634 const char *wcstr;
635 const char *rastr;
636 const char *scstr;
637 const char *type;
639 error = EIO;
642 * A NULL atx indicates a probe of the directly connected device.
643 * A non-NULL atx indicates a device connected via a port multiplier.
644 * We need to preserve atx for calls to ahci_ata_get_xfer().
646 * at is always non-NULL. For directly connected devices we supply
647 * an (at) pointing to target 0.
649 if (atx == NULL) {
650 at = ap->ap_ata[0]; /* direct attached - device 0 */
651 if (ap->ap_type == ATA_PORT_T_PM) {
652 kprintf("%s: Found Port Multiplier\n",
653 ATANAME(ap, atx));
654 return (0);
656 at->at_type = ap->ap_type;
657 } else {
658 at = atx;
659 if (atx->at_type == ATA_PORT_T_PM) {
660 kprintf("%s: Bogus device, reducing port count to %d\n",
661 ATANAME(ap, atx), atx->at_target);
662 if (ap->ap_pmcount > atx->at_target)
663 ap->ap_pmcount = atx->at_target;
664 goto err;
667 if (ap->ap_type == ATA_PORT_T_NONE)
668 goto err;
669 if (at->at_type == ATA_PORT_T_NONE)
670 goto err;
673 * Issue identify, saving the result
675 xa = ahci_ata_get_xfer(ap, atx);
676 xa->complete = ahci_ata_dummy_done;
677 xa->data = &at->at_identify;
678 xa->datalen = sizeof(at->at_identify);
679 xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
680 xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
682 switch(at->at_type) {
683 case ATA_PORT_T_DISK:
684 xa->fis->command = ATA_C_IDENTIFY;
685 type = "DISK";
686 break;
687 case ATA_PORT_T_ATAPI:
688 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
689 xa->flags |= ATA_F_AUTOSENSE;
690 type = "ATAPI";
691 break;
692 default:
693 xa->fis->command = ATA_C_ATAPI_IDENTIFY;
694 type = "UNKNOWN(ATAPI?)";
695 break;
697 xa->fis->features = 0;
698 xa->fis->device = 0;
699 xa->timeout = 1000;
701 if (ahci_ata_cmd(xa) != ATA_S_COMPLETE) {
702 kprintf("%s: Detected %s device but unable to IDENTIFY\n",
703 ATANAME(ap, atx), type);
704 ahci_ata_put_xfer(xa);
705 goto err;
707 ahci_ata_put_xfer(xa);
709 ata_fix_identify(&at->at_identify);
712 * Read capacity using SATA probe info.
714 if (le16toh(at->at_identify.cmdset83) & 0x0400) {
715 /* LBA48 feature set supported */
716 capacity = 0;
717 for (i = 3; i >= 0; --i) {
718 capacity <<= 16;
719 capacity +=
720 le16toh(at->at_identify.addrsecxt[i]);
722 } else {
723 capacity = le16toh(at->at_identify.addrsec[1]);
724 capacity <<= 16;
725 capacity += le16toh(at->at_identify.addrsec[0]);
727 if (capacity == 0)
728 capacity = 1024 * 1024 / 512;
729 at->at_capacity = capacity;
730 if (atx == NULL)
731 ap->ap_probe = ATA_PROBE_GOOD;
733 capacity_bytes = capacity * 512;
736 * Negotiate NCQ, throw away any ata_xfer's beyond the negotiated
737 * number of slots and limit the number of CAM ccb's to one less
738 * so we always have a slot available for recovery.
740 * NCQ is not used if ap_ncqdepth is 1 or the host controller does
741 * not support it, and in that case the driver can handle extra
742 * ccb's.
744 * NCQ is currently used only with direct-attached disks. It is
745 * not used with port multipliers or direct-attached ATAPI devices.
747 * Remember at least one extra CCB needs to be reserved for the
748 * error ccb.
750 if ((ap->ap_sc->sc_cap & AHCI_REG_CAP_SNCQ) &&
751 ap->ap_type == ATA_PORT_T_DISK &&
752 (le16toh(at->at_identify.satacap) & (1 << 8))) {
753 at->at_ncqdepth = (le16toh(at->at_identify.qdepth) & 0x1F) + 1;
754 devncqdepth = at->at_ncqdepth;
755 if (at->at_ncqdepth > ap->ap_sc->sc_ncmds)
756 at->at_ncqdepth = ap->ap_sc->sc_ncmds;
757 if (at->at_ncqdepth > 1) {
758 for (i = 0; i < ap->ap_sc->sc_ncmds; ++i) {
759 xa = ahci_ata_get_xfer(ap, atx);
760 if (xa->tag < at->at_ncqdepth) {
761 xa->state = ATA_S_COMPLETE;
762 ahci_ata_put_xfer(xa);
765 #if 0
766 if (at->at_ncqdepth >= ap->ap_sc->sc_ncmds) {
767 cam_sim_set_max_tags(ap->ap_sim,
768 at->at_ncqdepth - 1);
770 #endif
772 } else {
773 devncqdepth = 0;
776 model_len = sizeof(at->at_identify.model);
777 model_id = at->at_identify.model;
778 ahci_strip_string(&model_id, &model_len);
780 firmware_len = sizeof(at->at_identify.firmware);
781 firmware_id = at->at_identify.firmware;
782 ahci_strip_string(&firmware_id, &firmware_len);
784 serial_len = sizeof(at->at_identify.serial);
785 serial_id = at->at_identify.serial;
786 ahci_strip_string(&serial_id, &serial_len);
789 * Generate informatiive strings.
791 * NOTE: We do not automatically set write caching, lookahead,
792 * or the security state for ATAPI devices.
794 if (at->at_identify.cmdset82 & ATA_IDENTIFY_WRITECACHE) {
795 if (at->at_identify.features85 & ATA_IDENTIFY_WRITECACHE)
796 wcstr = "enabled";
797 else if (at->at_type == ATA_PORT_T_ATAPI)
798 wcstr = "disabled";
799 else
800 wcstr = "enabling";
801 } else {
802 wcstr = "notsupp";
805 if (at->at_identify.cmdset82 & ATA_IDENTIFY_LOOKAHEAD) {
806 if (at->at_identify.features85 & ATA_IDENTIFY_LOOKAHEAD)
807 rastr = "enabled";
808 else if (at->at_type == ATA_PORT_T_ATAPI)
809 rastr = "disabled";
810 else
811 rastr = "enabling";
812 } else {
813 rastr = "notsupp";
816 if (at->at_identify.cmdset82 & ATA_IDENTIFY_SECURITY) {
817 if (at->at_identify.securestatus & ATA_SECURE_FROZEN)
818 scstr = "frozen";
819 else if (at->at_type == ATA_PORT_T_ATAPI)
820 scstr = "unfrozen";
821 else if (AhciNoFeatures & (1 << ap->ap_num))
822 scstr = "<disabled>";
823 else
824 scstr = "freezing";
825 } else {
826 scstr = "notsupp";
829 kprintf("%s: Found %s \"%*.*s %*.*s\" serial=\"%*.*s\"\n"
830 "%s: tags=%d/%d satacap=%04x satafea=%04x NCQ=%s "
831 "capacity=%lld.%02dMB\n",
833 ATANAME(ap, atx),
834 type,
835 model_len, model_len, model_id,
836 firmware_len, firmware_len, firmware_id,
837 serial_len, serial_len, serial_id,
839 ATANAME(ap, atx),
840 devncqdepth, ap->ap_sc->sc_ncmds,
841 at->at_identify.satacap,
842 at->at_identify.satafsup,
843 (at->at_ncqdepth > 1 ? "YES" : "NO"),
844 (long long)capacity_bytes / (1024 * 1024),
845 (int)(capacity_bytes % (1024 * 1024)) * 100 / (1024 * 1024)
847 kprintf("%s: f85=%04x f86=%04x f87=%04x WC=%s RA=%s SEC=%s\n",
848 ATANAME(ap, atx),
849 at->at_identify.features85,
850 at->at_identify.features86,
851 at->at_identify.features87,
852 wcstr,
853 rastr,
854 scstr
858 * Additional type-specific probing
860 switch(at->at_type) {
861 case ATA_PORT_T_DISK:
862 error = ahci_cam_probe_disk(ap, atx);
863 break;
864 case ATA_PORT_T_ATAPI:
865 error = ahci_cam_probe_atapi(ap, atx);
866 break;
867 default:
868 error = EIO;
869 break;
871 err:
872 if (error) {
873 at->at_probe = ATA_PROBE_FAILED;
874 if (atx == NULL)
875 ap->ap_probe = at->at_probe;
876 } else {
877 at->at_probe = ATA_PROBE_GOOD;
878 if (atx == NULL)
879 ap->ap_probe = at->at_probe;
880 ahci_RegisterVolume(ap, at);
882 return (error);