Changeset 8 for trunk/src/ahci.c
- Timestamp:
- Sep 10, 2010, 11:30:39 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/ahci.c
r4 r8 37 37 /* -------------------------- function prototypes -------------------------- */ 38 38 39 static int exec_polled_cmd (AD_INFO *ai, int p, int d, int timeout,40 int cmd, ...);41 39 static void ahci_setup_device (AD_INFO *ai, int p, int d, u16 *id_buf); 42 40 static void _far timeout_callback (ULONG timer_handle, ULONG p1, ULONG p2); … … 265 263 266 264 /* set maximum command slot number */ 267 ai->cmd_max = (u16) ((ai->cap >> 8) & 31);265 ai->cmd_max = (u16) ((ai->cap >> 8) & 0x1f); 268 266 269 267 return(0); … … 404 402 * - This function is expected to be called with the spinlock released but 405 403 * the corresponding adapter's busy flag set. It will aquire the spinlock 406 * temporarily to allocate/free memory for ATA identify buffer.404 * temporarily to allocate/free memory for the ATA identify buffer. 407 405 */ 408 406 int ahci_scan_ports(AD_INFO *ai) … … 457 455 /* this port has a device attached and is ready to accept commands */ 458 456 ddprintf("port #%d seems to be attached to a device; probing...\n", p); 459 rc = exec_polled_cmd(ai, p, 0, 500, ATA_CMD_ID_ATA,460 AP_VADDR, (void _far *) id_buf, 512,461 AP_END);457 rc = ahci_exec_polled_cmd(ai, p, 0, 500, ATA_CMD_ID_ATA, 458 AP_VADDR, (void _far *) id_buf, 512, 459 AP_END); 462 460 463 461 if (rc != 0 || id_buf[ATA_ID_CONFIG] & (1U << 15)) { 464 462 /* this might be an ATAPI device; run IDENTIFY_PACKET_DEVICE */ 465 rc = exec_polled_cmd(ai, p, 0, 500, ATA_CMD_ID_ATAPI,466 AP_VADDR, (void _far *) id_buf, 512,467 AP_END);463 rc = ahci_exec_polled_cmd(ai, p, 0, 500, ATA_CMD_ID_ATAPI, 464 AP_VADDR, (void _far *) id_buf, 512, 465 AP_END); 468 466 } 469 467 … … 826 824 { 827 825 volatile u32 *cmds; 826 ADD_WORKSPACE _far *aws = add_workspace(iorb); 828 827 AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb); 829 828 P_INFO *port = ai->ports + iorb_unit_port(iorb); 830 829 ULONG timeout = (iorb->Timeout > 0) ? iorb->Timeout : DEFAULT_TIMEOUT; 831 830 u8 _far *port_mmio = port_base(ai, iorb_unit_port(iorb)); 832 int is_ncq = ((ai->cap & HOST_CAP_NCQ) &&833 ncq_capable &&834 !add_workspace(iorb)->no_ncq);835 831 int i; 836 832 837 /* NCQ disabled temporarily until non-NCQ commands are working fine */ 838 is_ncq = 0; 833 /* determine whether this will be an NCQ request */ 834 aws->is_ncq = ((ai->cap & HOST_CAP_NCQ) && ncq_capable && !aws->no_ncq); 835 836 /* NCQ disabled temporarily until non-NCQ commands are fully working */ 837 aws->is_ncq = 0; 839 838 840 839 /* check whether adapter is available */ … … 851 850 852 851 /* prevent NCQ/regular command mix */ 853 if (is_ncq && port->reg_cmds == 0 || !is_ncq && port->ncq_cmds == 0) { 852 if (aws->is_ncq && port->reg_cmds == 0 || 853 !aws->is_ncq && port->ncq_cmds == 0) { 854 854 855 855 /* Find next available command slot. We use a simple round-robin … … 857 857 * from stalling when new commands are coming in frequently. 858 858 */ 859 cmds = ( is_ncq) ? &port->ncq_cmds : &port->reg_cmds;859 cmds = (aws->is_ncq) ? &port->ncq_cmds : &port->reg_cmds; 860 860 for (i = 0; i <= ai->cmd_max; i++) { 861 861 if ((*cmds & (1UL << port->cmd_slot)) == 0) { 862 862 break; 863 863 } 864 if (++(port->cmd_slot) > =ai->cmd_max) {864 if (++(port->cmd_slot) > ai->cmd_max) { 865 865 port->cmd_slot = 0; 866 866 } … … 879 879 880 880 /* start timer for this IORB */ 881 ADD_StartTimerMS(&add_workspace(iorb)->timer, timeout, 882 (PFN) timeout_callback, iorb, 0); 883 884 /* update IORB and increment next command index */ 885 add_workspace(iorb)->queued_hw = 1; 886 add_workspace(iorb)->cmd_slot = port->cmd_slot; 887 if (++(port->cmd_slot) >= ai->cmd_max) { 888 port->cmd_slot = 0; 889 } 881 ADD_StartTimerMS(&aws->timer, timeout, (PFN) timeout_callback, iorb, 0); 882 883 /* update IORB */ 884 aws->queued_hw = 1; 885 aws->cmd_slot = port->cmd_slot; 890 886 891 887 /* issue command to hardware */ 892 d printf("issuing command on slot %d\n", port->cmd_slot);888 ddprintf("issuing command on slot %d\n", port->cmd_slot); 893 889 *cmds |= (1UL << port->cmd_slot); 894 if ( is_ncq) {890 if (aws->is_ncq) { 895 891 writel(port_mmio + PORT_SCR_ACT, (1UL << port->cmd_slot)); 896 892 readl(port_mmio + PORT_SCR_ACT); /* flush */ … … 899 895 readl(port_mmio + PORT_CMD_ISSUE); /* flush */ 900 896 897 /* make sure next cmd won't use the same slot to prevent starvation */ 898 if (++(port->cmd_slot) > ai->cmd_max) { 899 port->cmd_slot = 0; 900 } 901 901 spin_unlock(drv_lock); 902 902 return; … … 906 906 907 907 /* requeue this IORB; it will be picked up again in trigger_engine() */ 908 a dd_workspace(iorb)->processing = 0;908 aws->processing = 0; 909 909 spin_unlock(drv_lock); 910 910 } … … 916 916 * 917 917 * - We need to restore the BIOS configuration after we're done with this 918 * command because we might still need the BIOS to load additional drivers. 918 * command because someone might still call int 13 routines; sending 919 * asynchronous commands and waiting for interrupts to indicate completion 920 * won't work in such a scenario. 919 921 * - Our context hooks won't work while the device managers are initializing 920 922 * (they can't yield at init time). … … 951 953 } 952 954 953 /* restart port (includes the necessary port configuration */955 /* restart port (includes the necessary port configuration) */ 954 956 if (ahci_stop_port(ai, p) || ahci_start_port(ai, p, 0)) { 955 957 iorb_seterr(iorb, IOERR_ADAPTER_NONSPECIFIC); … … 983 985 if (add_workspace(iorb)->ppfunc != NULL) { 984 986 add_workspace(iorb)->ppfunc(iorb); 987 } else { 988 add_workspace(iorb)->complete = 1; 985 989 } 986 990 } … … 994 998 ahci_restore_bios_config(ai); 995 999 996 iorb_done(iorb); 1000 if (add_workspace(iorb)->complete | (iorb->Status | IORB_ERROR)) { 1001 aws_free(add_workspace(iorb)); 1002 iorb_done(iorb); 1003 } 997 1004 return; 1005 } 1006 1007 /****************************************************************************** 1008 * Execute polled ATA/ATAPI command. This function will block until the command 1009 * has completed or the timeout has expired, thus it should only be used during 1010 * initialization. Furthermore, it will always use command slot zero. 1011 * 1012 * The difference to ahci_exec_polled_iorb() is that this function executes 1013 * arbitrary ATA/ATAPI commands outside the context of an IORB. It's typically 1014 * used when scanning for devices during initialization. 1015 */ 1016 int ahci_exec_polled_cmd(AD_INFO *ai, int p, int d, int timeout, int cmd, ...) 1017 { 1018 va_list va; 1019 u8 _far *port_mmio = port_base(ai, p); 1020 u32 tmp; 1021 int rc; 1022 1023 /* verify that command slot 0 is idle */ 1024 if (readl(port_mmio + PORT_CMD_ISSUE) & 1) { 1025 ddprintf("port %d slot 0 is not idle; not executing polled cmd\n", p); 1026 return(-1); 1027 } 1028 1029 /* fill in command slot 0 */ 1030 va_start(va, cmd); 1031 if ((rc = v_ata_cmd(ai, p, d, 0, cmd, va)) != 0) { 1032 return(rc); 1033 } 1034 1035 /* start command execution for slot 0 */ 1036 ddprintf("executing polled cmd..."); 1037 writel(port_mmio + PORT_CMD_ISSUE, 1); 1038 1039 /* wait until command has completed */ 1040 while (timeout > 0 && (readl(port_mmio + PORT_CMD_ISSUE) & 1)) { 1041 mdelay(10); 1042 timeout -= 10; 1043 } 1044 ddprintf(" done (time left = %d)\n", timeout); 1045 1046 /* check error condition */ 1047 if ((tmp = readl(port_mmio + PORT_SCR_ERR)) != 0) { 1048 dprintf("SERR = 0x%08lx\n", tmp); 1049 return(-1); 1050 } 1051 if (((tmp = readl(port_mmio + PORT_TFDATA)) & 0x89) != 0) { 1052 dprintf("TFDATA = 0x%08lx\n", tmp); 1053 return(-1); 1054 } 1055 1056 return((timeout <= 0) ? -1 : 0); 998 1057 } 999 1058 … … 1119 1178 if (aws->ppfunc != NULL) { 1120 1179 aws->ppfunc(iorb); 1180 } else { 1181 aws->complete = 1; 1121 1182 } 1122 aws_free(aws); 1123 1124 /* move IORB to our temporary done queue */ 1125 iorb_queue_del(&ai->ports[p].iorb_queue, iorb); 1126 iorb_queue_add(&done_queue, iorb); 1183 1184 if (aws->complete) { 1185 /* this IORB is complete */ 1186 aws_free(aws); 1187 1188 /* move IORB to our temporary done queue */ 1189 iorb_queue_del(&ai->ports[p].iorb_queue, iorb); 1190 iorb_queue_add(&done_queue, iorb); 1191 } 1127 1192 1128 1193 /* clear corresponding bit in issued command bitmaps */ … … 1205 1270 void ahci_get_geometry(IORBH _far *iorb) 1206 1271 { 1272 dprintf("ahci_get_geometry(%d.%d.%d)\n", (int) iorb_unit_adapter(iorb), 1273 (int) iorb_unit_port(iorb), (int) iorb_unit_device(iorb)); 1274 1207 1275 ahci_exec_iorb(iorb, 0, cmd_func(iorb, get_geometry)); 1208 1276 } … … 1213 1281 void ahci_unit_ready(IORBH _far *iorb) 1214 1282 { 1283 dprintf("ahci_unit_ready(%d.%d.%d)\n", (int) iorb_unit_adapter(iorb), 1284 (int) iorb_unit_port(iorb), (int) iorb_unit_device(iorb)); 1285 1215 1286 ahci_exec_iorb(iorb, 0, cmd_func(iorb, unit_ready)); 1216 1287 } … … 1221 1292 void ahci_read(IORBH _far *iorb) 1222 1293 { 1294 dprintf("ahci_read(%d.%d.%d, %ld, %ld)\n", (int) iorb_unit_adapter(iorb), 1295 (int) iorb_unit_port(iorb), (int) iorb_unit_device(iorb), 1296 (long) ((IORB_EXECUTEIO _far *) iorb)->RBA, 1297 (long) ((IORB_EXECUTEIO _far *) iorb)->BlockCount); 1298 1223 1299 ahci_exec_iorb(iorb, 1, cmd_func(iorb, read)); 1224 1300 } … … 1229 1305 void ahci_verify(IORBH _far *iorb) 1230 1306 { 1307 dprintf("ahci_verify(%d.%d.%d, %ld, %ld)\n", (int) iorb_unit_adapter(iorb), 1308 (int) iorb_unit_port(iorb), (int) iorb_unit_device(iorb), 1309 (long) ((IORB_EXECUTEIO _far *) iorb)->RBA, 1310 (long) ((IORB_EXECUTEIO _far *) iorb)->BlockCount); 1311 1231 1312 ahci_exec_iorb(iorb, 0, cmd_func(iorb, verify)); 1232 1313 } … … 1237 1318 void ahci_write(IORBH _far *iorb) 1238 1319 { 1320 dprintf("ahci_write(%d.%d.%d, %ld, %ld)\n", (int) iorb_unit_adapter(iorb), 1321 (int) iorb_unit_port(iorb), (int) iorb_unit_device(iorb), 1322 (long) ((IORB_EXECUTEIO _far *) iorb)->RBA, 1323 (long) ((IORB_EXECUTEIO _far *) iorb)->BlockCount); 1324 1239 1325 ahci_exec_iorb(iorb, 1, cmd_func(iorb, write)); 1240 1326 } … … 1248 1334 int p = iorb_unit_port(iorb); 1249 1335 int d = iorb_unit_device(iorb); 1336 1337 dphex(((IORB_ADAPTER_PASSTHRU _far *) iorb)->pControllerCmd, 1338 ((IORB_ADAPTER_PASSTHRU _far *) iorb)->ControllerCmdLen, 1339 "ahci_execute_cdb(%d.%d.%d)", (int) iorb_unit_adapter(iorb), 1340 (int) iorb_unit_port(iorb), (int) iorb_unit_device(iorb)); 1250 1341 1251 1342 if (ad_infos[a].ports[p].devs[d].atapi) { … … 1266 1357 int d = iorb_unit_device(iorb); 1267 1358 1359 dphex(((IORB_ADAPTER_PASSTHRU _far *) iorb)->pControllerCmd, 1360 ((IORB_ADAPTER_PASSTHRU _far *) iorb)->ControllerCmdLen, 1361 "ahci_execute_cdb(%d.%d.%d)", (int) iorb_unit_adapter(iorb), 1362 (int) iorb_unit_port(iorb), (int) iorb_unit_device(iorb)); 1363 1268 1364 if (ad_infos[a].ports[p].devs[d].atapi) { 1269 1365 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED); … … 1272 1368 ahci_exec_iorb(iorb, 0, ata_execute_ata); 1273 1369 } 1274 }1275 1276 /******************************************************************************1277 * Execute polled ATA/ATAPI command. This function will block until the command1278 * has completed or the timeout has expired, thus it should only be used during1279 * initialization. Furthermore, it will always use command slot zero...1280 */1281 static int exec_polled_cmd(AD_INFO *ai, int p, int d, int timeout, int cmd, ...)1282 {1283 va_list va;1284 u8 _far *port_mmio = port_base(ai, p);1285 u32 tmp;1286 int rc;1287 1288 /* verify that command slot 0 is idle */1289 if (readl(port_mmio + PORT_CMD_ISSUE) & 1) {1290 ddprintf("port %d slot 0 is not idle; not executing polled cmd\n", p);1291 return(-1);1292 }1293 1294 /* fill in command slot 0 */1295 va_start(va, cmd);1296 if ((rc = v_ata_cmd(ai, p, d, 0, cmd, va)) != 0) {1297 return(rc);1298 }1299 1300 /* start command execution for slot 0 */1301 ddprintf("executing polled cmd...");1302 writel(port_mmio + PORT_CMD_ISSUE, 1);1303 1304 /* wait until command has completed */1305 while (timeout > 0 && (readl(port_mmio + PORT_CMD_ISSUE) & 1)) {1306 mdelay(10);1307 timeout -= 10;1308 }1309 ddprintf(" done (time left = %d)\n", timeout);1310 1311 /* check error condition */1312 if ((tmp = readl(port_mmio + PORT_SCR_ERR)) != 0) {1313 dprintf("SERR = 0x%08lx\n", tmp);1314 return(-1);1315 }1316 if (((tmp = readl(port_mmio + PORT_TFDATA)) & 0x89) != 0) {1317 dprintf("TFDATA = 0x%08lx\n", tmp);1318 return(-1);1319 }1320 1321 return((timeout <= 0) ? -1 : 0);1322 1370 } 1323 1371
Note:
See TracChangeset
for help on using the changeset viewer.